1

我目前正在使用 mcrypt.java 来加密和解密来自服务器端和客户端 cryptojs 的数据,但我遇到了一些问题,因为当我加密任何字符串时,java 和 JavaScript 都会显示不同的结果。

好吧,我正在阅读有关 AES 加密的方法和填充方案的信息,并且一些博客谈论将 CBC 模式与 NoPadding 一起使用是不正确的,并且更好/正确地将 CBC 与 Pkcs7 或其他填充一起使用。

任何人都可以向我解释与此相关的事情吗?

4

1 回答 1

5

如果您在 ECB/CBC 块密码模式下执行 AES 加密,则需要填充您的明文,除非您的明文是块大小的倍数。你当然可以确保你的明文总是精确的 N 个块,但实际上你会创建自己的填充模式。

许多库(例如 PHP 中的 mcrypt)在秘密进行填充时没有指定任何填充。00他们只是用有价值的字节填充最后一个块。这样做的效果是您可以加密ASCII 兼容的文本,然后它将以null 终止。在大多数语言(不使用空终止)中,也可以使用一种trim方法来删除此填充。然而,这不是官方的填充模式。当然,这种方案只有在您的纯文本不以控制字符结尾时才有效。所以它不适用于任何二进制明文。

使用 PKCS#7 填充绝对更好。删除 PKCS#7 填充对于任何明文都是确定性的。这意味着您可以加密任何值,包括 UTF-16 编码文本和任何二进制值。如果 PKCS#7 填充不可用,那么自己实现它相对容易——这当然值得付出努力。CBC 模式的 PKCS#7 填充的唯一缺点是,当明文已经是块大小的 N 倍时,它可能需要额外的填充块。这样做的原因是明文可能会被误解为填充。

请注意,填充和填充错误不适合检测密文是否在传输过程中发生更改。填充预言机非常容易实现,并且可以以 128 倍于明文大小(以字节为单位)显示明文(!!!)。因此,如果您想为明文提供完整性和真实性,请使用经过身份验证的操作模式或 MAC(HMAC 或 CMAC)。

如果您真的不能错过用于填充的字节,请查看 CTR 或您的分组密码的类似流操作模式。


编辑

还有密文窃取或 CTS 可用于 CBC 模式。它用得不多,因为它有三种不同的版本,你应该确定使用的是哪一种。

现在更常见的是使用计数器模式(CTR 模式)或基于它的认证模式(如果完全使用分组密码)。CTR 模式不需要任何填充,因为它是流式操作模式。

于 2013-10-15T15:59:29.097 回答