心急的童鞋直接看這里Demo
運(yùn)行之后可以去在線加密網(wǎng)站驗(yàn)證
AES(Advanced Encryption Standard)高級加密標(biāo)準(zhǔn),又稱Rijndael加密法抡医,是美國聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)浦徊。這個(gè)標(biāo)準(zhǔn)用來替代原先的DES
AES的五種加密模式
AES有五種加密模式(CBC坛善、ECB喘蟆、CTR镇眷、OCF季惯、CFB)
1.電碼本模式(Electronic Code Book (ECB))
2.密碼分組鏈接模式(Cipher Block Chaining (CBC))
3.計(jì)算器模式(Counter (CTR))
4.密碼反饋模式(Cipher FeedBack (CFB))
5.輸出反饋模式(Output FeedBack (OFB))
在iOS用到的一般就是ECB和CBC兩種吠各。
ECB-電碼本模式
ECB是最簡單的塊密碼加密模式臀突,加密前根據(jù)加密塊大小(AES加密塊固定為128位)分成若干塊贾漏,之后將每塊使用相同的密鑰單獨(dú)加密候学,所以加密塊相同的明文會(huì)生成相同的密文。
CBC-密碼分組鏈接模式
CBC模式對于每個(gè)待加密的密碼塊在加密前會(huì)先與前一個(gè)密碼塊的密文異或然后再用加密器加密纵散。第一個(gè)明文塊與一個(gè)叫初始化向量的數(shù)據(jù)塊異或梳码。
OK,最簡單的理論理解了伍掀,就來看iOS最重要的干貨:加解密函數(shù)CCCrypt
CCCrypt - 加解密函數(shù)
CCCryptorStatus CCCrypt(
CCOperation op, /* kCCEncrypt, etc. */
CCAlgorithm alg, /* kCCAlgorithmAES128, etc. */
CCOptions options, /* kCCOptionPKCS7Padding, etc. */
const void *key,
size_t keyLength,
const void *iv, /* optional initialization vector */
const void *dataIn, /* optional per op and alg */
size_t dataInLength,
void *dataOut, /* data RETURNED here */
size_t dataOutAvailable,
size_t *dataOutMoved)
重要的參數(shù)說明:
- CCOperation op:加密kCCEncrypt掰茶,解密kCCDecrypt
- CCAlgorithm alg:加密算法,這里kCCAlgorithmAES128和kCCAlgorithmAES是一樣的,AES加密塊固定是128位蜜笤,咱們常說的AES128濒蒋、192、256加密只是加密秘鑰的長度不同(當(dāng)然加密處理輪數(shù)也不同把兔,這里就不做說明了)
- CCOptions options:
kCCOptionPKCS7Padding:填充模式
kCCOptionECBMode:ECB模式 - size_t keyLength:參數(shù)是下面這些沪伙,看到很多博客不管是128還是256,這里都寫kCCBlockSizeAES128县好,這是不對的围橡,這樣加密出來的其實(shí)還是128加密
enum {
kCCKeySizeAES128 = 16,
kCCKeySizeAES192 = 24,
kCCKeySizeAES256 = 32,
kCCKeySizeDES = 8,
kCCKeySize3DES = 24,
kCCKeySizeMinCAST = 5,
kCCKeySizeMaxCAST = 16,
kCCKeySizeMinRC4 = 1,
kCCKeySizeMaxRC4 = 512,
kCCKeySizeMinRC2 = 1,
kCCKeySizeMaxRC2 = 128,
kCCKeySizeMinBlowfish = 8,
kCCKeySizeMaxBlowfish = 56,
};
- iv:偏移向量,CBC模式下需要缕贡,不傳默認(rèn)16位0翁授,ECB不需要
關(guān)于CCCrypt中的key和keyLength
AES數(shù)據(jù)塊長度為128位,所以IV長度需要為16個(gè)字符(ECB模式不用IV)善绎,密鑰根據(jù)指定密鑰位數(shù)分別為16黔漂、24、32個(gè)字符禀酱,IV與密鑰超過長度則截取炬守,不足則在末尾填充'\0'補(bǔ)足
key和keyLength之間的關(guān)系,現(xiàn)在算是搞明白了剂跟,key就是咱們傳入的密鑰减途,keyLength是決定密鑰長度的,也就是aes128曹洽,192鳍置,256的真正區(qū)別了,如果傳入的key是32位送淆,也就是256要求的位數(shù)税产,但是keyLength選擇了kCCKeySizeAES128,那么真正的key其實(shí)是截取前面的16位,如果key傳入16位辟拷,但是keyLength選擇了kCCKeySizeAES256撞羽,那就是密鑰位數(shù)不夠,會(huì)自動(dòng)補(bǔ)全到32位
雖然密鑰長度不夠的話會(huì)自動(dòng)補(bǔ)齊或者截取衫冻,不過感覺還是傳入正確的密鑰比較好诀紊,128的keysize=16,192keysize=24隅俘,256keysize=32
好了邻奠,直接上代碼
Demo
需要引入 #import <CommonCrypto/CommonCrypto.h>
AES256 ECB模式加密
+(NSData *)dataByAes256ECB:(NSData *)data key:(NSString *)key mode:(CCOperation)operation {
char keyPtr[kCCKeySizeAES256 + 1];//選擇aes256加密,所以key長度應(yīng)該是kCCKeySizeAES256为居,32位
bzero(keyPtr, sizeof(keyPtr));//清零
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];//秘鑰key轉(zhuǎn)成cString
NSUInteger dataLength = data.length;
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void * buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(operation,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode,//ECB模式
keyPtr,
kCCKeySizeAES256,
NULL,//選擇ECB模式碌宴,不需要向量
data.bytes,
dataLength,
buffer,
bufferSize,
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
NSData * result = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
return result;
}
free(buffer);
return nil;
}
AES128 CBC模式加解密
+(NSData *)dataByAes128CBC:(NSData *)data key:(NSString *)key mode:(CCOperation)operation iv:(NSString *)iv {
char keyPtr[kCCKeySizeAES128 + 1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = data.length;
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void * buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
NSString * initIv = iv;
char ivPtr[kCCBlockSizeAES128+1];
memset(ivPtr, 0, sizeof(ivPtr));
[initIv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
CCCryptorStatus cryptStatus = CCCrypt(operation,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keyPtr,
kCCKeySizeAES128,
ivPtr,
data.bytes,
dataLength,
buffer,
bufferSize,
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
NSData * result = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
return result;
}
free(buffer);
return nil;
}