将 Crypto++ AES 加密移植到 PHP 的 mcrypt 时密钥大小不正确

2023-12-25

早些时候,我设法将一些 C++ CryptoPP Rijndael_128 CBC 代码移植到 MCrypt PHP,但现在我遇到了 CFB 模式的问题。 C++ 和 PHP 结果不匹配(第一个字节匹配,但这可能是巧合,其他一切都不是)。通过一些诊断,PHP 的 mcrypt 似乎没有正确设置密钥长度?

这是 C++(为了简单起见,删除了诊断和杂项):

CFB_Mode<AES>::Encryption encryptor(g_encrypt_key, AES::DEFAULT_KEYLENGTH, g_encrypt_iv);

StringSource ss( sInput.c_str(), true, 
        new StreamTransformationFilter( encryptor, 
            new HexEncoder( new StringSink( sEncryptedOut ) )
        ));

这是 PHP:

$cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CFB, '')
mcrypt_generic_init($cipher, $g_encrypt_key, $g_encrypt_iv);

$sEncryptedOutput = mcrypt_generic( $cipher, $sInput);
mcrypt_generic_deinit($cipher);
mcrypt_module_close($cipher);

g_encrypt_key and g_encrypt_iv都是 16 字节长,并且字节与 C++ 和 PHP 版本匹配。对于 PHP 版本,它是由字节构造的二进制字符串(是的,我已经检查过它们是相同的)。

我已经添加了对 PHP 版本的调用来检查$cipher的块大小、密钥大小等。 块大小和iv大小均为16;支持的密钥大小报告为 16、24 和 32 - 全部符合预期。

我认为问题在于密钥大小被报告为 32 字节。查看 mcrypt 文档,设置密钥大小的唯一方法是提供所需大小的密钥。但我传递的是 16 字节密钥!那么为什么它报告存在 32 字节密钥呢?如果CFB模式必须使用32字节密钥,那么为什么CryptoPP会接受它?解决办法是什么?我可以强制 PHP 使用已提供的 16 字节密钥吗?或者我是否缺少一个参数,该参数默认为 CryptoPP 中的设置与 MCrypt 中的设置不同?

我使用 CFB 模式是因为我想最小化生成的加密数据的长度。填充将引入的几个字节在此应用程序中确实很重要。

我需要能够在 C++ 中加密/解密,但只能在 PHP 中加密。 AES 对于我的应用程序来说可以说是杀伤力过大 - 我需要的最低限度是“对字节进行良好的加扰”,以便数据中各个字节的功能不明显。


已经有一段时间了,但几年前我在使用 CFB 的 mcrypt 和 openSSL 方面遇到了一些类似的问题。最后,我发现 mcrypt 在 CFB 模式下使用了与 openssl 不同的默认反馈链大小。也就是说,我相信CFB中的openSSL AES128使用了128位的块大小和反馈大小,而mcrypt使用了128位的块大小和8位的反馈大小。我无法证实这一点,这只是当时基于阅读一些旧论坛帖子的猜测。不管这个理论的真实性如何,我并不是唯一一个或第一个遇到这个特殊问题的人。

我的解决方案是像你自己一样使用 nOFB。根据PHP mcrypt 库参考 http://www.theserverpages.com/php/manual/en/ref.mcrypt.php MCRYPT_MODE_NOFB强制反馈链等于算法块大小,在本例中为 AES128 (Rijndael) 的 128 位块/反馈,它与manpage http://man.cx/mcryptmcrypt 模块说明了有关 nOFB 的信息。这很好,因为我发现 nO​​FB 反馈与块大小同步。因此,nOFB 中的 mcrypt 和 OpenSSL 现在都是 AES128 的 128 位密钥/iv/块/反馈大小,并且一切正常。

就 PHP 报告 256 位密钥大小(32 字节)而言,返回当前密码算法密钥大小的函数实际上返回最大密钥大小,文档中没有明确说明。我知道这一点是因为我现在一直在各种项目中使用的小类与 openSSL 以及 CBC 或 nOFB 中的任何其他 AES 库完美配合。如果 mcrypt 用额外的 128 位空字符串或其他内容填充我的 128 位(16 个字符)密钥,则情况不会如此,并且无论如何在技术上都是不正确的。

这并不是一个很好的答案,但我在几年前对密码学的一次非常业余的尝试中得到了最好的答案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 Crypto++ AES 加密移植到 PHP 的 mcrypt 时密钥大小不正确 的相关文章

随机推荐