這幾天項目要求做一個加密功能凝危,采用的是 AES 加密波俄,要求是 CBC 方式NoPadding。項目需求只有加密功能蛾默,所以這里沒有對應(yīng)的解密方法懦铺。不過照著加密的方法推導(dǎo)一下,結(jié)合網(wǎng)上的文章看一看支鸡,差不多也能寫出來冬念。
項目并沒有用GTMBase64做轉(zhuǎn)碼,大致的流程是:
加密內(nèi)容----轉(zhuǎn)成 NSData ---- AES 加密并得到結(jié)果 ---- 把結(jié)果轉(zhuǎn)成16進(jìn)制傳給后臺 ---- 完事兒
首先需要的參數(shù):
- key:移動端和后端約定的秘鑰苍匆。
- ivValue:可選的初始化向量刘急,我這方法里就沒用到這個值。
- content:就是你需要加密的內(nèi)容浸踩。
接下來是加密部分:
導(dǎo)入頭文件#import <CommonCrypto/CommonCrypto.h>
代碼
+ (NSString *)AES128Encrypt:(NSData *)plainText keyString:(NSString *)keyStr
{
// 這里的 plainText 是由需要加密的內(nèi)容 string 轉(zhuǎn)成 NSData 的叔汁,下面會詳細(xì)說.
NSUInteger dataLength = [plainText length];
unsigned long diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);
unsigned long newSize = 0;
if(diff > 0)
{
newSize = dataLength + diff;
}
char dataPtr[newSize];
memcpy(dataPtr, [plainText bytes], [plainText length]);
for(int i = 0; i < diff; i++)
{
// 0x0000 代表 no padding
dataPtr[i + dataLength] = 0x0000;
}
size_t bufferSize = newSize + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
memset(buffer, 0, bufferSize);
size_t numBytesCrypted = 0;
// 這里的 byte 表示初始化向量,下面會詳細(xì)說.
// Byte byte[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
0x0000, // 0x00 表示 no padding检碗,其他的根據(jù)情況來選
[keyStr UTF8String], // keyPtr
kCCKeySizeAES128,
NULL, // 原本是初始化向量值,不過是可選的据块,所以用 NULL
dataPtr,
sizeof(dataPtr),
buffer,
bufferSize,
&numBytesCrypted);
if (cryptStatus == kCCSuccess) {
NSData *resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
// 將加密好的數(shù)據(jù)轉(zhuǎn)成16進(jìn)制的字符
return [self hexStringFromData:resultData];
}
free(buffer);
return nil;
}
+ (NSString *)hexStringFromData:(NSData *)data {
Byte *bytes = (Byte *)[data bytes];
// 下面是Byte 轉(zhuǎn)換為16進(jìn)制。
NSString *hexStr = @"";
for(int i=0; i<[data length]; i++) {
NSString *newHexStr = [NSString stringWithFormat:@"%x",bytes[i] & 0xff]; //16進(jìn)制數(shù)
newHexStr = [newHexStr uppercaseString];
if([newHexStr length] == 1) {
newHexStr = [NSString stringWithFormat:@"0%@",newHexStr];
}
hexStr = [hexStr stringByAppendingString:newHexStr];
}
return hexStr;
}
說明
- 這里說說上面代碼里提到的 plainText折剃。
項目里要求先把 content 轉(zhuǎn)成 data另假,如果 data 的長度不足64位需要在末尾補(bǔ)0。所以原本是 string 類型的 plainText 在這兒就是 data 類型了怕犁,可以根據(jù)自己的需要改一下子就行边篮。把代碼放在下面,有需要的就用奏甫,沒需要的就略過吧戈轿。 - 還有一個初始化向量,剛開始后臺給了這個值阵子,就是代碼里那16個0x00的 byte 數(shù)組思杯。但是后來發(fā)現(xiàn)這個向量值用不上,所以本文一開頭兒也說了這玩意兒可選挠进,看具體情況來吧色乾。
- 最后把加密完的內(nèi)容轉(zhuǎn)成16進(jìn)制也是項目需求誊册,具體轉(zhuǎn)不轉(zhuǎn)不強(qiáng)求,只要后臺能解密出來就行暖璧。
NSString *contStr = @"這是一個天大的秘密內(nèi)容";
// 把內(nèi)容轉(zhuǎn)成 data
NSData *contData = [contStr dataUsingEncoding:NSUTF8StringEncoding];
// 創(chuàng)建一個64位的 byte 數(shù)組
//Byte *byteData = (Byte*)malloc(64); // 這樣創(chuàng)建的數(shù)組在位數(shù)不夠時好像并不會補(bǔ)0
Byte byteData[64] = {0};
// 得到轉(zhuǎn)化成 data 的內(nèi)容的 byte 數(shù)組
char *byteObj = (char *)[contData bytes];
// 把內(nèi)容的 byte 遍歷到新的 byte 數(shù)組里去
for (int i=0; i<contData.length; i++) {
byteData[i] = byteObj[i];
}
// 得到新的 data
// 這個 '48' 也是個不解的地方案怯,為啥不是 64 呢?
NSData *encryptData = [[NSData alloc]initWithBytes:byteData length:48];
// 把新的 data 進(jìn)行 AES 加密漆撞,并得到加密后的 string
NSString *aesStr = [AESEncrypt AES128Encrypt:encryptData keyString:gkey];
NSLog(@"加密:%@",aesStr);
最后
不明白的地方殴泰,如果哪位明白人兒能搞懂,麻煩你給翻譯翻譯浮驳,謝謝了悍汛!
當(dāng)然了,自己也得找找帖子琢磨琢磨至会,以下是參考過的帖子离咐。
iOS AES128 CBC No Padding加密解密
AES加密 - iOS與Java的同步實現(xiàn)
[拿走直接用] iOS加密:AES+Base64