加密类型
对称加密
对称加密又称公开密钥加密,加密和解密都会用到同一个密钥,如果密钥被攻击者获得,此时加密就失去了意义。常见的对称加密算法有DES、3DES、AES(本文重点)、Blowfish、IDEA、RC5、RC6。
非对称加密
非对称加密又称共享密钥加密,使用一对非对称的密钥,一把叫做私有密钥,另一把叫做公有密钥;公钥加密只能用私钥来解密,私钥加密只能用公钥来解密。常见的公钥加密算法有:RSA、ElGamal、背包算法、Rabin(RSA的特例)、迪菲-赫尔曼密钥交换协议中的公钥加密算法、椭圆曲线加密算法)。
AES
加密流程
图片来至于网络
AES加密模式
-
ECB模式(Electronic Code Book Mode)
-
CBC模式(Cipher Block Chaining Mode)
-
CFB模式(Cipher Feedback Mode)
-
OFB模式(Output Feedback Mode)
-
CTR模式(Counter Mode)
-
PCBC模式(Propagating Cipher Block Chaining Mode)
除ECB模式外,其余都需要初始向量 也就是偏移量 这里主要说一下ECB模式。
ECB模式(Electronic Code Book Mode)
ECB模式是最早采用和最简单的模式,它将加密的数据分成若干组,每组的大小跟加密密钥长度相同,然后每组都用相同的密钥进行加密。
优点:有利于并行计算;误差不会累计(互不干扰)。
缺点:可能对明文进行主动攻击。
无论什么语言系统,AES的算法总是相同的, 因此导致结果不一致的原因在于 加密设置的参数不一致 。于是先来看看在两个平台使用AES加密时需要统一的几个参数。
- 密钥长度(Key Size)
- 加密模式(Cipher Mode)
- 填充方式(Padding)
- 初始向量(Initialization Vector)
填充方式
由于块加密只能对特定长度的数据块进行加密,因此CBC、ECB模式需要在最后一数据块加密前进行数据填充。(CFB,OFB和CTR模式由于与key进行加密操作的是上一块加密后的密文,因此不需要对最后一段明文进行填充)
在iOS SDK中提供了PKCS7Padding,而JDK则提供了PKCS5Padding。原则上PKCS5Padding限制了填充的Block Size为8 bytes,而Java实际上当块大于该值时,其PKCS5Padding与PKCS7Padding是相等的:每需要填充χ个字节,填充的值就是χ。
AES 加密解密代码实现
iOS 使用 RNCryptor 的OC端库。
代码实现很简单
对字符串进行AES加密后在进行base64编码
//字符串转data
NSData *stringData = [[separatedArray lastObject] dataUsingEncoding:NSUTF8StringEncoding];
//进行AES加密
NSData *encryptData = [RNEncryptor encryptData:stringData withSettings:kRNCryptorAES256Settings password:key error:nil];
//进行base64编码
encryptString = [GTMBase64 stringByWebSafeEncodingData:encryptData padded:YES];
base64字符串进行base64解码在AES解密
//字符串转data
NSData *encryptedData = [GTMBase64 decodeData:[tempEnStr dataUsingEncoding:NSUTF8StringEncoding]];
//AES解密
NSData *decryptedData = [RNDecryptor decryptData:encryptedData
withPassword:key
error:nil];
//data转String
NSString* decodeString = [[NSString alloc] initWithData:decryptedData
encoding:NSUTF8StringEncoding];
Base64编码
普通的 Base64编码,得到的字符串可能存在 +/=号,比如+号,如果放在链接里请求后端接收的时候就变成了空格。所以需要使用安全的Base64编码,
可以上面使用了三方库 GTMBase64,或者自己转。方法如下:
// base64 url 编码
- (NSString *)base64UrlEncoder:(NSString *)str {
NSData *data = [[str dataUsingEncoding:NSUTF8StringEncoding] base64EncodedDataWithOptions:0];
NSMutableString *base64Str = [[NSMutableString alloc] initWithData:data encoding:NSUTF8StringEncoding];
base64Str = (NSMutableString * )[base64Str stringByReplacingOccurrencesOfString:@"+" withString:@"-"];
base64Str = (NSMutableString * )[base64Str stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
base64Str = (NSMutableString * )[base64Str stringByReplacingOccurrencesOfString:@"=" withString:@""];
return base64Str;
}
// base64 url 解码
- (NSString *)base64UrlDecoder:(NSString *)str {
NSMutableString *base64Str = [[NSMutableString alloc] initWithString:str];
base64Str = (NSMutableString * )[base64Str stringByReplacingOccurrencesOfString:@"-" withString:@"+"];
base64Str = (NSMutableString * )[base64Str stringByReplacingOccurrencesOfString:@"_" withString:@"/"];
NSInteger mod4 = base64Str.length % 4;
if (mod4) {
[base64Str appendString:[@"====" substringToIndex:(4 - mod4)]];
}
NSData *data = [[NSData alloc] initWithBase64EncodedString:base64Str options:0];
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}