早些时候,我设法将一些 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_keyg_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 对于我的应用程序来说可以说是杀伤力过大 - 我需要的最低限度是“对字节进行良好的加扰”,以便数据中各个字节的功能不明显。

有帮助吗?

解决方案

这是一段时间,但我曾与mcrypt的和OpenSSL使用CFB几年前一些类似的问题。最后,我发现mcrypt的使用不同的默认反馈链大小比CFB模式的OpenSSL。也就是说,相信一个OpenSSL的AES128在CFB中使用的128位的块大小和反馈尺寸,同时使用的mcrypt 128位的块大小和8个比特的反馈的大小。我没有办法证实这一点,它是在基于阅读一些老论坛帖子的时候只是猜测。无论是理论的真理,我是不是唯一的人还是第一次有这种特殊的问题。

对我来说,解决方案是使用NOFB如己。按照 PHP的mcrypt库参考 MCRYPT_MODE_NOFB力反馈链为等于算法的块大小,在此情况下为AES128(Rijndael算法),这与什么手册页约NOFB的mcrypt的模块的状态。这是好一切,我发现说NOFB反馈是同步的块大小。因此,两个的mcrypt和OpenSSL在NOFB是现在的128位密钥/ IV /块/反馈尺寸AES128和一切工作得很好。

至于PHP报告256bit的keysizes(32个字节),即返回当前密算法的密钥长度实际上返回的最大密钥大小,这是不明确的文档中所述的功能。我知道这是因为我的小班级我现在用所有的时间用于各种项目工作完全正常使用OpenSSL和CBC或NOFB任何其他AES库。这不会是这种情况,如果是的mcrypt填充我的128位(16个字符)键与空字符串的附加的128位,或什么,并且不会在技术上正确无论如何。

不是真的一个很好的答案,但最好我基于一个非常外行进军加密几年前。

其他提示

查核phpseclib:

http://phpseclib.sourceforge.net/

您可以设置任何你想要的密钥长度和块大小。

例如。 $ AES-> setKeyLength(128)或$ AES-> setKeyLength(256);

我遇到了这个问题 - 有几点。默认情况下,PHP Rijndael 模式将反馈循环设置为 8 位 - AES 需要与 IV/Key 的长度相同。

您可以使用模式“ncfb”而不是“cfb”或 MCRYPT_MODE_CFB 来完成此操作。

有关编写 aes_cfb_128 兼容 PHP 的完整详细信息,请参见以下 Security Stackexchange 问题: Erlang 和 PHP 之间的 aes cfb 128 解密/加密问题. 。它的缺点是(来自汤姆·利克):

...对于 CFB 和 OFB(它们彼此不同并且不能互换使用),您必须担心“反馈长度”,它不一定在各种加密库中得到清晰的记录。加密和解密都必须使用相同的反馈长度才能互操作。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top