使用openssl AES ECB PKCS5Padding加解密遇到的问题
AES简介
AES,英文全称Advanced Encryption Standard,高级加密标准。AES描述的算法是对称密钥算法,也就是说,加密和解密数据使用的是相同的密钥。
AES是两位比利时密码学家Vincent Rijmen和Joan Daemen开发的Rijndael分组密码的子集。分组密码的意思是,把明文分成一组一组的,每组长度相等,每次只加密一组数据,直到将整个明文加密完。
在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(1个字节8位)。但密钥的长度可以使用128位、192位或256位。密钥的长度不同,加密轮数也不同1。对于128位的密钥,其加密轮数为10轮,也就是说,一个明文分组会被加密10轮。从安全性来看,AES256安全性最高。从性能看,AES128性能最高。本质原因是它们的加密处理轮数不同2。
关于使用AES加解密,网上介绍的文章已经比较多了,我这里主要记录一下,自己在使用过程中,遇到的问题以及如何解决的。我们使用的加解密模式是ECB模式,密钥长度128位,采用的填充是默认的PKCS5Padding,C/C++和JAVA的示例源代码在这里。
加密前的填充与解密后的剔除填充处理
遇到的问题是,解密之后得到的结果多余了一些数据,因为不知道源数据的长度,所以不知道怎么截取。
最初没有想到,在加密之前填充的值,加密之后仍然是不变的。比如加密之前,填充了5个字节的0x5,那么在解密之后,得到的结果后面仍然是有5个字节的0x5。根据PKCS5Padding的填充规则,在解密后,最后一个字节肯定为填充数据的长度,所以是可以准确地删除填充的数据的,便可以得到原始数据。
简单来说,在加密之前,需要对源数据进行填充处理。解密之后,需要根据结果最后一个字节进行剔除填充处理。
16进制字符串转字节数组处理
因为AES的处理单位是字节,所以如果提供的数据是以16进制字符串格式,那么要先转成字节数组。
比如说,给一串128位的密钥:861C3E4077A5395897CB29C31C501B9C,这是16进制字符串格式,使用其进行加密或解密时,就要先转换成char key[16]数组:
key[0] = 0x86
key[1] = 0x1C
key[2] = 0x3E
…
加密后得到的结果,原本就是存于字节数组中的。为了方便提供给使用方,一般是将其转换成16进制字符串格式表示,那么拿着这个16进制字符串密文结果进行解密时,就得先将其转换成字节数组再进行处理。
或者有的是使用base64对加密后的字节数组进行加密,那么使用其进行解密时,就要先进行base64解密,得到的便是需要的字节数组,就可以继续后续处理了。
方式不同,但原理是一样的。