项目中需要对文件进行加密和解密,考虑通过openssl来做,因此这两天尝试去搞了一下。参照csdn上的一些源码去实现了一下,稍微有点问题。主要是加密后再解密时,尾部有乱码。一开始找不到原因,于是考虑不写代码,直接调用openssl来做加密,解密,看看会不会有问题。命令很简单:
加密环节:
openssl enc -e -aes-128-cbc -pass file:./keyFile -in plainFile -out encryptFile
-e表示加密
-aes-128-cbc:aes表示加密的方法基于aes标准,128是密钥长度,cbc是aes中一种。aes除了cbc还有ecb,cfb等。具体有哪些用openssl enc -e -list可以查看。
-keyFile就是保存对称密钥的文件
-plainFile是要加密的文件,也就是明文文件
-encryptFile就是加密后的文件
解密环节:
openssl enc -d -aes-128-cbc -pass file:./keyFile -in encryptFile -out plainFile
-d表示解密。
其它的参数很容易看明白。
测试的结果,发现,通过命令行调用的话,解密后的文件非常正常,没有乱码。
之后用代码去实现,无非就是通过system(char* cmd)函数去调用上面两个命令,结果也是好的。
那说明前面通过代码的方式去实现,某个细节上有问题。后来查到了一篇文章,链接如下:
[Solved] AES 256-cbc encryption C++ using OpenSSL | 9to5Answer
原因就在于加密是分段进行的,aes-128的话,每段的长度为16个字节。如果文件的长度,不能被16整除,剩余的字节,凑不够16个的话,需要进行填充(padding),而且用0填充。
size_t inputslength = message.length();//原始文件的长度
unsigned char aes_input[inputslength];
unsigned char aes_key[AES_KEYLENGTH];//秘钥长度
const size_t encslength = ((inputslength + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;//真正加密的时候,明文的长度(填充后的)
unsigned char enc_out[encslength];
unsigned char dec_out[inputslength];
memset(enc_out, 0, sizeof(enc_out)); memset(dec_out, 0, sizeof(dec_out));//填充部分变为0
AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv, AES_ENCRYPT);//加密,密文长度可能比明文长度大
按照这种去操作,尾部出现乱码的问题就消失了