一、AES 加密报错:java.security.InvalidAlgorithmParameterException: ECB mode cannot use IV
1、问题背景
AES 加解密需使用的 算法(参数 - 算法名称/加密模式/数据填充方式),之前我使用的 "AES/EBC/PKCS5Padding" 时,如果采用 偏移向量 会报错:java.security.InvalidAlgorithmParameterException: ECB mode cannot use IV
原因是 EBC 模式无需 IV,上述报错的字面意思也很好理解
2、解决方式:
EBC 模式改为 CBC 模式即可(具体如下描述)
二、AES 加密,ECB模式无需IV,pkcs5padding和zeropadding两种填充方式
1、AES-EBC模式,加密时,如果明文不足16的倍数, 会填充为16的倍数(这里假设填充0),此时分组加密后,得到的密文也是16的倍数。解密时,同样的分组解密,也就是说,解密后的明文同样是16的倍数。请问它是如何计算出正确的明文长度的?
举例:明文:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14] 15位字节,密文:[x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x] 16位,按照分组解密后,应该是16字节, 他是如何将填充物去掉,得到真正明文15字节的? 求解惑
2、填充规则 - 重点了解
如果原始数据是N字节的整数倍,则添加一个值为N的额外字节块。这是必要的,这样解译算法就可以确定最后一个块的最后一个字节是一个pad字节,表示添加的填充字节的数量还是明文消息的一部分。
考虑一个明文消息,它是N字节的整数倍,明文的最后一个字节是01。由于没有其他信息,解密算法将无法确定最后一个字节是明文字节还是pad字节。
但是,通过在01明文字节之后为每个值N增加N个字节,解译算法始终可以将最后一个字节视为补码字节,并从密文的末尾去掉适当数目的补码字节;
所述要根据最后一个字节的值剥离的字节数
例如{1,2,3,4,5,6,7,8,9},总共9个数值,取余16后是9,需要补充7个7,则最后数据变为{1,2,3,4,5,6,7,8,9,7,7,7,7,7,7,7}
需要特别注意一种情况:如果数据的个数刚好是16的倍数,那就要在补充16个字节(一定要)。例如{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},填充后的数据是{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16},始终能通过最后一个字节判断出来 添加了几位填充物。
三、AES 加密算法中,ECB和CBC模式有什么区别
1、ECB模式 - 电子密本方式:
ECB 其实非常简单,就是将数据按照8个字节一段进行加密或解密得到一段段的8个字节的密文或者明文,最后一段不足8个字节(一般补0或者F),按照需求补足8个字节进行计算(并行计算),之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。
其优点:简单;有利于并行计算;误差不会被传递;
缺点:不能隐藏明文的模式;可能对明文进行主动攻击;
2、CBC 模式 - 密文分组链接方式 - 安全性更好
其优点:不容易主动攻击,安全性好于ECB,是SSL、IPSec的标准;
缺点:不利于并行计算;误差传递;需要初始化向量IV;
3、CBC(密文分组链接方式)有点麻烦,它的实现机制使加密的各段数据之间有了联系。其实现的机理、加密步骤如下:
首先将数据按照8个字节一组进行分组得到D1、D2…Dn(若数据不是8的整数倍,用指定的PADDING数据补位)
第一组数据D1与初始化向量 IV 异或后的结果进行DES加密得到第一组密文C1(初始化向量IV为全零)
第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2
之后的数据以此类推,得到Cn
按顺序连为C1C2C3…Cn即为加密结果。