一、加密基礎(chǔ)知識
密鑰:它是在明文轉(zhuǎn)換為密文或?qū)⒚芪霓D(zhuǎn)換為明文的算法中輸入的參數(shù)。密鑰分為對稱密鑰與非對稱密鑰。
對稱加密:同一個密鑰可以同時用作信息的加密和解密,這種加密方法稱為對稱加密,也稱為單密鑰加密。常用的是DES。
非對稱加密:非對稱加密算法需要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對,如果用公開密鑰對數(shù)據(jù)進(jìn)行加密,只有用對應(yīng)的私有密鑰才能解密;如果用私有密鑰對數(shù)據(jù)進(jìn)行加密,那么只有用對應(yīng)的公開密鑰才能解密。因為加密和解密使用的是兩個不同的密鑰,所以這種算法叫作非對稱加密算法。
常用的是RSA羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)
因為RSA更安全但是更慢,DES速度更快,但相對安全性低,所以有下圖的經(jīng)典加密方式。
使用DES加密數(shù)據(jù)的內(nèi)容,再使用RSA加密DES的密鑰。
一、MD5
MD5(Message Digest Algorithm MD5)是一種摘要算法,它可以通過任意長度的數(shù)據(jù),計算出固定長度的摘要內(nèi)容。
通過對比摘要內(nèi)容可以知道傳輸?shù)臄?shù)據(jù)是否被修改,MD5有以下的特點
1、壓縮性:任意長度的數(shù)據(jù),算出的MD5值長度都是固定的。
2、容易計算:從原數(shù)據(jù)計算出MD5值很容易。
3、抗修改性:對原數(shù)據(jù)進(jìn)行任何改動,哪怕只修改1個字節(jié),所得到的MD5值都有很大區(qū)別。
4、強抗碰撞:已知原數(shù)據(jù)和其MD5值,想找到一個具有相同MD5值的數(shù)據(jù)(即偽造數(shù)據(jù))是非常困難的。
//導(dǎo)入CommonCrypto
#import <CommonCrypto/CommonCrypto.h>
//MD5計算字符串
-(void)md5
{
//需要MD5的內(nèi)容
NSString *str = @"The more you care, the more you have to lose.";
//系統(tǒng)提供的md5加密的核心函數(shù)是c語言的函數(shù),轉(zhuǎn)換成C語言的字符串
const charchar *strChar = [str UTF8String];
//計算長度
//C語言的char類型的數(shù)組,長度為宏定義,因為md5加密是將任意長度的二進(jìn)制存儲為固定長度的二進(jìn)制
unsigned char result[CC_MD5_DIGEST_LENGTH];
//將加密好的值存儲到result中
//參數(shù):源數(shù)據(jù) ,源數(shù)據(jù)的長度 , 加密后存儲的位置
CC_MD5(strChar, (CC_LONG)strlen(strChar), result);
//聲明可變字符串用來存儲
NSMutableString *md5_Str = [NSMutableString string];
//遍歷所有result元素,進(jìn)行16進(jìn)制編碼
for (int i = 0; i< CC_MD5_DIGEST_LENGTH; i++) {
[md5_Str appendFormat:@"%02X",result[i]];
}
//得到MD5摘要
NSLog(@"end %@",md5_Str);
}
如果要計算數(shù)組或者字典,就把它們轉(zhuǎn)化成NSData類型,再將NSData轉(zhuǎn)化為NSString,就可以用上面的方法如果要計算復(fù)雜對象的MD5,那么要對復(fù)雜對象進(jìn)行歸檔處理,如下
//復(fù)雜對象計算MD5
-(void)archiverMD5
{
Person *per = [[Person alloc]init];
per.name = @"問問";
//創(chuàng)建可變Data
NSMutableData *mData = [NSMutableData data];
//創(chuàng)建歸檔工具
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:mData];
//歸檔
[archiver encodeObject:per forKey:@"per"];
//結(jié)束歸檔
[archiver finishEncoding];
//加密
//這個mData是復(fù)雜對象歸檔產(chǎn)生的,不能用UTF8轉(zhuǎn)成NSString,出來的是空
NSString *str = [[NSString alloc]initWithData:mData encoding:NSUTF8StringEncoding];
NSLog(@"%@",str);
//轉(zhuǎn)換成char*
// const char *strChar1 = str.UTF8String;
const void*strChar = mData.bytes;
//創(chuàng)建char數(shù)組
unsigned char result[CC_MD5_DIGEST_LENGTH];
//MD5
CC_MD5(strChar, (CC_LONG)strlen(strChar), result);
// CC_MD5(strChar, CC_MD5_DIGEST_LENGTH, result);
//聲明可變字符串
NSMutableString *resultStr = [NSMutableString stringWithCapacity:2];
//遍歷result數(shù)組
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[resultStr appendFormat:@"%02X",result[i]];
}
//得到復(fù)雜對象的MD5
NSLog(@"archiver %@ %u",resultStr,(CC_LONG)strlen(strChar));
}
二、base64
Base64是網(wǎng)絡(luò)上最常見的用于傳輸8Bit字節(jié)代碼的編碼方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的詳細(xì)規(guī)范。Base64編碼可用于在HTTP環(huán)境下傳遞較長的標(biāo)識信息。
//base 64加密
-(void)encodeBase64
{
//需要加密的數(shù)據(jù)
NSString *sourceStr = @"我是base64 sads@#%%$&^&##adgffad()?><:sgfdavxc34tggfdgcvbag32984-/3/23-0=g3da1g51dfa53f";
//轉(zhuǎn)成NSData
NSData *sourceData = [sourceStr dataUsingEncoding:NSUTF8StringEncoding];
//加密
NSString *result = [sourceData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
//加密后可能會有一些反斜杠,加號等
NSLog(@"base64---%@",result);
//解密
[self dencodeBase64WithStr:result];
}
//base 64解密,參數(shù)為base64加密后的字符串
-(void)dencodeBase64WithStr:(NSString*)base64_str
{
NSData *data = [[NSData alloc]initWithBase64EncodedString:base64_str options:NSDataBase64DecodingIgnoreUnknownCharacters];
NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"base64 解 -- %@",str);
}
三、KeyChain
鑰匙串(英文:Keychain)是蘋果公司Mac OS中的密碼管理系統(tǒng)。它在Mac OS 8.6中被導(dǎo)入,并且包括在了所有后續(xù)的Mac OS版本中,包括Mac OS X。一個鑰匙串可以包含多種類型的數(shù)據(jù):密碼(包括網(wǎng)站,F(xiàn)TP服務(wù)器,SSH帳戶,網(wǎng)絡(luò)共享,無線網(wǎng)絡(luò),群組軟件,加密磁盤鏡像等),私鑰,電子證書和加密筆記等。
KeyChain是一種對稱加密
1.首先拖入KeychainItemWrapper的.m和.h文件
2.在工程的Build Phases設(shè)置的Compile Sources下給KeychainItemWrapper.m后面加上-fno-objc-arc,讓這個非arc的類可以在arc工程下編譯
3.在Link Binary With Libraries下面加上Security.framework
準(zhǔn)備工作就完成了
keyChain加密的鑰匙串對象,在整個工程都可以取到,是全局的
#pragma mark -- keychain加密
//加密
-(void)keyChain
{
//創(chuàng)建鑰匙串對象,identifier是當(dāng)前鑰匙串的標(biāo)記,解密時根據(jù)標(biāo)記獲得對應(yīng)的鑰匙串
KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc]initWithIdentifier:@"myKeyChain" accessGroup:nil];
//當(dāng)我們需要存儲的時候,需要使用系統(tǒng)的鍵,而不能用自定義的
id stringKey = (__bridge id)kSecAttrAccount;
//加密存儲
[wrapper setObject:@"我是wrapper" forKey:stringKey];
}
//解密
-(void)keyChainSolution
{
//得到鑰匙串對象
KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc]initWithIdentifier:@"myKeyChain" accessGroup:nil];
//
NSString *receiveStr = [wrapper objectForKey:(__bridge id)kSecAttrAccount];
NSLog(@"%@",receiveStr);
}