AES加解密
IOS项目的Utils工具类里面暴露两个方法
//MARK: AES加解密
+ (NSString *)aesEncrypt:(NSString *)sourceStr;
+ (NSString *)aesDecrypt:(NSString *)secretStr;
跟其他端确定秘钥和偏移量
#define GL_AES_KEY @"aef01238765abcde"
#define GL_AES_IV GL_AES_KEY
核心逻辑
加解密: kCCEncrypt - 加密,kCCDecrypt - 解密
填充:kCCOptionPKCS7Padding
加密方式:
/*
//CBC模式
kCCOptionPKCS7Padding
//ECB模式
kCCOptionPKCS7Padding | kCCOptionECBMode
*/
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keyPtr,
kCCBlockSizeAES128,
ivPtr,//ECB模式下可以为NULL
[sourceData bytes],
dataLength,
buffer,
buffersize,
&numBytesEncrypted);
代码实现
- 注意AES的加密方式:默认是CBC加密方式,EBC方式的加密可以允许不需要IV偏移量
- 该输出方式为16进制,如果需要base64,可以对应代码注释里面修改(加解密两处处)
//MARK: AES加解密相关 start
+ (NSString *)aesEncrypt:(NSString *)sourceStr {
if (!sourceStr) {
return nil;
}
//秘钥
char keyPtr[kCCKeySizeAES256 + 1];
bzero(keyPtr, sizeof(keyPtr));
[GL_AES_KEY getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
//向量
char ivPtr[kCCBlockSizeAES128 + 1];
bzero(ivPtr, sizeof(ivPtr));
[GL_AES_IV getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
NSData *sourceData = [sourceStr dataUsingEncoding:NSUTF8StringEncoding];
NSUInteger dataLength = [sourceData length];
size_t buffersize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(buffersize);
size_t numBytesEncrypted = 0;
/*
//CBC模式
kCCOptionPKCS7Padding
//ECB模式
kCCOptionPKCS7Padding | kCCOptionECBMode
*/
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keyPtr,
kCCBlockSizeAES128,
ivPtr,//ECB模式下可以为NULL
[sourceData bytes],
dataLength,
buffer,
buffersize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
NSData *encryptData = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
//对加密后的二进制数据进行base64转码
//return [encryptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
//转换为16进制字符串
NSMutableString *output = [NSMutableString stringWithCapacity:encryptData.length * 2];
if (encryptData && encryptData.length > 0) {
Byte *datas = (Byte*)[encryptData bytes];
for(int i = 0; i < encryptData.length; i++){
[output appendFormat:@"%02x", datas[i]];
}
}
return output;
} else {
free(buffer);
return nil;
}
}
+ (NSString *)aesDecrypt:(NSString *)secretStr {
if (!secretStr) {
return nil;
}
//先对加密的字符串进行base64解码
//NSData *decodeData = [[NSData alloc] initWithBase64EncodedString:secretStr options:NSDataBase64DecodingIgnoreUnknownCharacters];
//先对加密的字符串进行16进制解码
NSData *decodeData = [self convertHexStrToData:secretStr];
//秘钥
char keyPtr[kCCKeySizeAES256 + 1];
bzero(keyPtr, sizeof(keyPtr));
[GL_AES_KEY getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
//向量
char ivPtr[kCCBlockSizeAES128 + 1];
bzero(ivPtr, sizeof(ivPtr));
[GL_AES_IV getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [decodeData length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
/*
//CBC模式
kCCOptionPKCS7Padding
//ECB模式
kCCOptionPKCS7Padding | kCCOptionECBMode
*/
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keyPtr,
kCCBlockSizeAES128,
ivPtr,//ECB模式下可以为NULL
[decodeData bytes],
dataLength,
buffer,
bufferSize,
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
NSData *data = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return result;
} else {
free(buffer);
return nil;
}
}
// 16进制转NSData
+ (NSData *)convertHexStrToData:(NSString *)str {
if (!str || [str length] == 0) {
return nil;
}
NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:20];
NSRange range;
if ([str length] % 2 == 0) {
range = NSMakeRange(0, 2);
} else {
range = NSMakeRange(0, 1);
}
for (NSInteger i = range.location; i < [str length]; i += 2) {
unsigned int anInt;
NSString *hexCharStr = [str substringWithRange:range];
NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr];
[scanner scanHexInt:&anInt];
NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1];
[hexData appendData:entity];
range.location += range.length;
range.length = 2;
}
return hexData;
}