AES 美国国家安全局采用的加密方法,MAC 系统自带的钥匙串也是采用的AES 加密方法
有两种模式
CBC 模式 链式加密 ,密码块链,使用一个秘钥和一个初始化向量,对数据执行加密。
ECB 电子密码本方法加密,数据拆分成块,独立加密。
mac 系统已经集成openssl 工具,可以直接文本进行加密
1 打开终端 桌面新建一个文件夹,cd 到里面,touch一个abc.txt
2 openssl enc -des-ecb -K 616263 -nosalt -in abc.txt -out msg1.bin
enc 代表加密
-des-ecb 代表ecb 模式
-k 代表 key 值
-nosalt 代表不加盐
-in abc.txt 代表 读取里面内容
-out msg1.bin 代表输出为msg1.bin 二进制文件
3 xxd 查看二进制文件
xxd msg1.bin
AES是开发中常用的加密算法之一。然而由于前后端开发使用的语言不统一,导致经常出现前端加密而后端不能解密的情况出现。然而无论什么语言系统,AES的算法总是相同的, 因此导致结果不一致的原因在于 加密设置的参数不一致 。于是先来看看在两个平台使用AES加密时需要统一的几个参数。
密钥长度(Key Size)
加密模式(Cipher Mode)
填充方式(Padding)
初始向量(Initialization Vector)
密钥长度
AES算法下,key的长度有三种:128、192和256 bits。由于历史原因,JDK默认只支持不大于128 bits的密钥,而128 bits的key已能够满足商用安全需求。因此本例先使用AES-128。(Java使用大于128 bits的key方法在文末提及)
加密模式
AES属于块加密(Block Cipher),块加密中有CBC、ECB、CTR、OFB、CFB等几种工作模式。本例统一使用CBC模式。
填充方式
由于块加密只能对特定长度的数据块进行加密,因此CBC、ECB模式需要在最后一数据块加密前进行数据填充。(CFB,OFB和CTR模式由于与key进行加密操作的是上一块加密后的密文,因此不需要对最后一段明文进行填充)
在iOS SDK中提供了PKCS7Padding,而JDK则提供了PKCS5Padding。原则上PKCS5Padding限制了填充的Block Size为8 bytes,而Java实际上当块大于该值时,其PKCS5Padding与PKCS7Padding是相等的:每需要填充χ个字节,填充的值就是χ。
初始向量
使用除ECB以外的其他加密模式均需要传入一个初始向量,其大小与Block Size相等(AES的Block Size为128 bits),而两个平台的API文档均指明当不传入初始向量时,系统将默认使用一个全0的初始向量。
引入NSString+Encryption.h" 文件
CocoaSecurity 框架基本实现了所有的加密方式
#import "ViewController.h"
#import "NSString+Encryption.h"
#import "CocoaSecurity.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self aesecbMode];
}
/**
AES CBC 模式加密的使用
CocoaSecurity 是一个用于加解密的框架,封装了各种加密方法的使用,用此框架来校验NSString+Encryption.h 加解密结果是否一样
CocoaSecurity 框架,解密的时候传入的参数都是16进制
*/
- (void)aescbcMode{
NSString *plainText = @"你好";
// key 16字节的字符串,就等于128 bite
// key支持 128 192 256 bite,分别对象 16 24 32 长度单位
// 如果长度错误,就会跑出异常
NSString *key128 = @"0123456789ABCDEF";
// 16进制字符串
NSString *key128Hex = @"30313233343536373839414243444546";
NSString *iv = @"0123456789ABCDEF";
// 16进制字符串
NSString *ivHex = @"30313233343536373839414243444546";
CocoaSecurityResult *result = [CocoaSecurity aesEncrypt:plainText hexKey:key128Hex hexIv:ivHex];
NSString *aesBase64 = [plainText aesEncryptWithKey:key128 iv:iv];
NSData *aesData = [plainText aesEncryptWithDataKey:[key128 dataUsingEncoding:NSUTF8StringEncoding] dataIv:[iv dataUsingEncoding:NSUTF8StringEncoding]];
NSLog(@"SecurityResult加密:\r\n%@ --- %@",result.base64,result.hexLower);
NSLog(@"NSString+Encryption加密:\r\n%@ --- %@",aesBase64,aesData);
// 解密
NSString *decryptStr = [aesBase64 aesBase64StringDecryptWithHexKey:key128Hex hexIv:ivHex];
NSData *data = [NSString aesDecryptWithData:aesData dataKey:[key128 dataUsingEncoding:NSUTF8StringEncoding] dataIv:[iv dataUsingEncoding:NSUTF8StringEncoding]];
// 使用CocoaSecurity 和 封装的方法 加解密结果进行校验
NSLog(@"解密:%@ --- %@",decryptStr, [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}
/**
AES EBC 模式加解密,EBC 模式
*/
- (void)aesecbMode{
NSString *plainText = @"123";
NSString *key128 = @"0123456789ABCDEF";
// key 16进制形式
NSString *key128Hex = @"30313233343536373839414243444546";
NSString *aesBase64 = [plainText aesECBEncryptWithKey:key128];
NSData *aesData = [plainText aesECBEncryptWithDataKey:[key128 dataUsingEncoding:NSUTF8StringEncoding]];
NSLog(@"加密:%@ --- %@",aesBase64, aesData);
// 解密
NSString *decStr = [aesBase64 aesECBBase64StringDecryptWithHexKey:key128Hex];
NSData *decData = [NSString aesECBDecryptWithData:aesData withDataKey:[key128 dataUsingEncoding:NSUTF8StringEncoding]];
NSLog(@"解密:%@---%@",decStr, [[NSString alloc]initWithData:decData encoding:NSUTF8StringEncoding]);
}
/**
AEC 框架是<CommonCrypto/CommonCrypto.h>
加解密所用的同一个核心方法
@param option 加密还是解密 枚举类型 kCCEncrypt 加密 kCCDecrypt 解密
@param kCCAlgorithmAES128 加密算法 默认是AES
@param mode kCCOptionPKCS7Padding 为CBC 加密 默认是CBC 加密
kCCOptionPKCS7Padding | kCCOptionECBMode 为ECB 加密
@param bytes] 加密秘钥
@param length] 秘钥长度
@param bytes] IV 初始化向量
@param bytes] 加密的数据
@param length] 数据的长度
@param buffer 密文缓冲区
@param bufferSize 缓冲区的大小
@param encryptedSize
@return 加密的结果
*/
// CCCryptorStatus cryptStatus = CCCrypt(option,
// kCCAlgorithmAES128,
// mode,
// [key bytes], // Key
// [key length], // kCCKeySizeAES
// [iv bytes], // IV
// [data bytes],
// [data length],
// buffer,
// bufferSize,
// &encryptedSize);
@end