首先在Mac上其实是自带了OpenSSL库,OpenSSL提供了很多的加密算法,我们在终端中可以用OpenSSL提供的加密算法指令来使用,当然我们也可以去通过调用OpenSSL提供的API来使用。
这里介绍下enc指令的作用,OpenSSL提供了很多的对称加密算法指令,enc就是把这些加密算法指令统一集成到enc指令中。当用户使用时,只需使用enc,指定加密算法,就是完成了单独的加密算法指令完成的操作。而且,enc中指定的加密算法指令可能并没有以单独指令的形式存在,所以我们调用enc是最安全的。
举个DES用ECB加密方法的终端命令
echo -n hello | openssl enc -des-ecb -K 616263 -nosalt | base64 这个命令的意思就是将hello以不换行的形式输出到后面 | 其实就是起一个管道的作用,然后去调用enu指令 后面的-des-ecb就是加密算法和加密方式,-K 就是指定密钥 然后nosalt就是设置不加盐,如果我们不去指定盐,以及我们不去设置不加盐的话,那么系统会随机的帮我们生成一个盐,后面的| 其实也是一个转接的作用| base64就是将加密的结果转成base64,之所以要去转成base64其实就是为了之后我们得到的结果好看以及,不然的话加密是对二进制数据进行加密,这样得到的数据不太好看。
这里需要注意的Key也就是密钥在终端中是要以16进制的形式存在的,iv也应该是以16位数字的形式存在。iv默认为16个0
还有就是需要去注意-k小写k 和-K也就是大写K的区别,可以去看官网的解释
https://www.openssl.org/docs/manmaster/man1/enc.html
也查阅了一些资料大概是这样的意思
-k是用来生成key和iv的序列。
-K,是用来指定密钥也就是key的。
关于IV向量其实大多数框架都是通过生成都是通过一个数组,然后数组中存放8个数就比如说在ios中的EncryptionTools框架中就是通过下面来做的,下面就是基于这个做一个简单的浅析。
uint8_t iv[8] = {2,3,4,5,6,7,0,0};
然后在EncryptionTools框架在内部会这么使用,下面就是先定义一个uIv,然后下面的self.blockSize其实就是16,因为我们这里用的是AES128这种加密方式。其中bzero函数就是置字节字符串s的前n个字节为零。
uint8_t cIv[self.blockSize];
bzero(cIv, self.blockSize);
int option = 0;
if (iv) {
//获取指定长度的数据。如果length大于数据长度,则使用数据长度作为指定长度。
[iv getBytes:cIv length:self.blockSize];
//下面是CBC的加密方式的选择
option = kCCOptionPKCS7Padding;
} else {
//下面是ECB的加密方式的选择
option = kCCOptionPKCS7Padding | kCCOptionECBMode;
}
在苹果提供的类中会有这么写,上面的blockSize就是根据下面这个来判断的,如果iv向量不足16的话就全部用0来代替上面的[iv getBytes:cIv length:self.blockSize];就是把IV里面的内容往civ里面写。
/*!
@enum Block sizes
@discussion Block sizes, in bytes, for supported algorithms.
@constant kCCBlockSizeAES128 AES block size (currently, only 128-bit
blocks are supported).
@constant kCCBlockSizeDES DES block size.
@constant kCCBlockSize3DES Triple DES block size.
@constant kCCBlockSizeCAST CAST block size.
*/
enum {
/* AES */
kCCBlockSizeAES128 = 16,
/* DES */
kCCBlockSizeDES = 8,
/* 3DES */
kCCBlockSize3DES = 8,
/* CAST */
kCCBlockSizeCAST = 8,
kCCBlockSizeRC2 = 8,
kCCBlockSizeBlowfish = 8,
};
下面是根据算法的不同来觉得密钥的长度的
enum {
kCCKeySizeAES128 = 16,
kCCKeySizeAES192 = 24,
kCCKeySizeAES256 = 32,
kCCKeySizeDES = 8,
kCCKeySize3DES = 24,
kCCKeySizeMinCAST = 5,
kCCKeySizeMaxCAST = 16,
kCCKeySizeMinRC4 = 1,
kCCKeySizeMaxRC4 = 512,
kCCKeySizeMinRC2 = 1,
kCCKeySizeMaxRC2 = 128,
kCCKeySizeMinBlowfish = 8,
kCCKeySizeMaxBlowfish = 56,
};
在这个框架内部有这么使用,其中的keyString就是我们输入的key也就是密钥,一样不足keySize的长度的,就都是用0来代替的
NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
uint8_t cKey[self.keySize];
bzero(cKey, sizeof(cKey));
[keyData getBytes:cKey length:self.keySize];
还有需要补充的是,因为在加密或者解密的过程对明文进行加密或者为密文进行解密的最大长度是有要求的,所以我们的明文或者密文是要符合一定的规范的,因为加密算法的需求,明文字节必须按照block进行填充对齐,才能方便进行加密运算,所以就有了kCCOptionPKCS7Padding 这是一种填充模式。大概就是这样子的一个实现过程,填充字符串由一个字节序列组成,每个字节填充该填充字节序列的长度。如果块长度为6,数据长度为7,数据是AA AA AA AA AA AA AA 填充之后变为AA AA AA AA AA AA AA 05 05 05 05 05。