1 回答
TA贡献1815条经验 获得超10个赞
PHP 代码使用块大小为 256 位的 Rijndael。SunJCE Provider 不支持此功能,仅支持 AES(它是 Rindael 的子集,块大小为 128 位)。因此,第二个 Java 代码片段也不起作用。因此必须使用像 BouncyCastle (BC) 这样的第三方提供商。
Java/BC代码中有两个bug:
与 PHP 代码相反,没有应用 CBC。必须使用 来更改此设置
CBCBlockCipher
。BC 的零填充变体与 mcrypt 变体不同。BC 变体总是填充,即即使明文的长度已经对应于块大小的整数倍(此处为 32 字节),mcrypt 变体也不会(即后者仅在明文长度不填充的情况下填充)对应于块大小的整数倍)。
由于根据描述,明文已经对应于块大小的整数倍,因此 mcrypt 变体不会填充。在 Java/BC 代码中,如果根本不使用填充,就可以实现这一点。
但要小心:如果明文的长度不对应于块大小的整数倍,那么当然必须使用填充(考虑到与 PHP 代码中使用的零填充变体的兼容性)。
这两个问题都可以通过更换线路来解决
ZeroBytePadding c = new ZeroBytePadding(); PaddedBufferedBlockCipher pbbc = new PaddedBufferedBlockCipher(rijndael, c);
经过
BufferedBlockCipher pbbc = new BufferedBlockCipher(new CBCBlockCipher(rijndael));
那么两个代码产生的密文是相同的。
一些附加说明:
使用密钥作为 IV 通常没有用。由于出于安全原因,IV 对于给定密钥只能使用一次,因此每次加密都必须使用新密钥。
通常在实践中,每次加密都会生成一个新的、随机的 IV。使用标准(即 AES)通常更安全,而不是使用块大小为 256 位的 Rijndael,后者不是标准。
零填充并不可靠(此外,正如您所经历的,有几种变体可能会导致问题)。更可靠的是 PKCS7 填充。
- 1 回答
- 0 关注
- 144 浏览
添加回答
举报