由于项目中,登录请求过程中涉及到用户数据的传输,为了用户数据的安全性考虑,决定在请求与相应中使用加密传输的方式。查找了相关资料后发现,目前最广泛的是使用AES+RSA组合加密的方式。即采用对称加密与非对称加密相结合的方式,综合了对称加密的高效与非对称加密的安全性,是目前大多数项目采用的方式。其大致的思路如下:
首先使用AES对称加密加密要传输的数据(由于数据可能会比较大,所以如果使用RSA非对称加密的话,就很耗性能,影响用户体验),然后用非对称加密RSA来加密AES加密所使用的密钥key,最后把AES加密后的数据,与RSA加密后的key发给服务器,同理后台也使用此方法来进行数据传输。
下面就针对AES与RSA加密的方式以及项目中遇到的问题做下简单的说明。
首先先看下加密的代码:
// 使用AES128 加密
//随机生成16位字符串的AES 加密的密钥key
NSString *key = [SecurityUtil randomlyGenerated16BitString];
NSLog(@"AES加密的秘钥key=%@",key);
NSLog(@"disJson = %@",[kutils JsonSerializer:dicJson]);
NSString *encodeBase64 = aesEncryptString([kutils JsonSerializer:dicJson], key);
NSLog(@"AES128加密:%@",encodeBase64);
NSString *decryptedText = aesDecryptString(encodeBase64, key);
NSLog(@"AES解密后的%@", decryptedText);
/************************
RAS 加密 ASE的KEY
****************************/
//给随机KEY 加密
NSString *encWithPubKey = [SecurityUtil encryptString:key publicKey:RSApublicKey];//RSApublicKey RSA加密的公钥
NSLog(@"RSA加密后的key:%@",encWithPubKey);
NSMutableDictionary *encryptJsonDict = [NSMutableDictionary dictionary];
[encryptJsonDict setValue:encWithPubKey forKey:@"key"];
[encryptJsonDict setValue:encodeBase64 forKey:@"value"];
dicJson = encryptJsonDict;
解密的代码
NSDictionary *temDic = [kutils JsonDeserializer:dataStr];//json解析
NSString *key = [temDic valueForKey:@"key"];
NSString *value = [temDic valueForKey:@"value"];
//RSA公钥解密服务端传过来的AES加密的key
if (key == nil) {
NSLog(@"发送登录请求后传过来的字典其中的key为nil");
}
NSString *AES_key = [SecurityUtil decryptString:key?:@"key" publicKey:RSApublicKey];
//然后使用key 来解密AES加密后的value
if (AES_key && value) {
NSString *dicString = aesDecryptString(value, AES_key);
NSLog(@"解密后的dicStrign = %@",dicString);
dic = [kutils JsonDeserializer:dicString];
} else {
NSLog(@"AES_key 或则value为nil AES_key = %@ value = %@",AES_key,value);
}
项目中遇到的问题:
- AES加密后的数据服务端无法解析
原因分析:由于 当时我使用的AES加密,设置了填充方式与初始向量,交流后发现我们呢后台使用Java的AES加密,他们说找不到设置这两项的方法(我这里觉得肯定是可以设置),没办法,只好没有设置初始向量以及填充方式设置为kCCOptionECBMode | kCCOptionPKCS7Padding
NSString const *kInitVector = @"";//@"A-16-Byte-String";
size_t const kKeySize = kCCKeySizeAES128;
NSData * cipherOperation(NSData *contentData, NSData *keyData, CCOperation operation) {
NSUInteger dataLength = contentData.length;
void const *initVectorBytes = [kInitVector dataUsingEncoding:NSUTF8StringEncoding].bytes;
void const *contentBytes = contentData.bytes;
void const *keyBytes = keyData.bytes;
size_t operationSize = dataLength + kCCBlockSizeAES128;
void *operationBytes = malloc(operationSize);
if (operationBytes == NULL) {
return nil;
}
size_t actualOutSize = 0;
CCCryptorStatus cryptStatus = CCCrypt(operation,
kCCAlgorithmAES,
kCCOptionECBMode | kCCOptionPKCS7Padding,
keyBytes,
kKeySize,
initVectorBytes,
contentBytes,
dataLength,
operationBytes,
operationSize,
&actualOutSize);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:operationBytes length:actualOutSize];
}
free(operationBytes);
operationBytes = NULL;
return nil;
}
关于AES加密参数的说明,这里有更加详细的说明大家可以参考:AES加密
- 后台发送过来的AES加密后数据iOS端无法正确解析
此问题很奇怪,因为在demo测试时候,我的客户端是可以正确解析的,但是当在项目中测试的时候发现解析不了,(测试时用的数据很小)最后交流中发现问题所在,我iOS 上AES生成的随机密钥key是字符串格式的,而后台端Java直接是生成二进制格式的密钥key,两端格式没有统一,最后后代改为使用字符串格式的密钥key后,就可以正常解析了。
说明:RSA的公钥我这里采用的Java后台生成的经过base64后的字符串。
网友评论