php - 找出 PHP 的 mcrypt 创建的确切 key

标签 php mcrypt rijndael

我正在维护的 PHP 应用程序使用 Rijndael_256 和 EBC_MODE 加密以及 mcrypt。有趣的是, key 不是 256 位长,而是只有 160 位。根据 mcrypt_encrypt文档中,如果键太小,则用\0 填充以获得所需的大小。

The key with which the data will be encrypted. If it's smaller than the required keysize, it is padded with '\0'. It is better not to use ASCII strings for keys.

这似乎发生在line 1186 in mcrypt.c开始时左右并修改第1213行的 key 。

假设我们有 $key = 'abcdefghijkm'; ,它太短了,但是 PHP 的 mcrypt 实现确保在使用 RIJNDAEL_256 时将其扩展到 32 个字符(或 256 位)。最终的 key 会是什么样子?

我问这个问题是因为正在构建另一个使用相同加密数据但采用另一种语言的应用程序。准确地说,Perl,我正在使用 Crypto::Rijndael 。对于给定的示例 key ,我必须提供给 Crypto::Rijndael (或任何其他相关 key )才能再次解密数据的确切 key 是什么?

更新

使用 Perl,我可以生成一个用\0 填充的 key pack('a32', 'my Secret key'); (或 Z32), length() 将报告 32,并且 Crypt::Rijndael 模块接受 key 。查看 PHP mcrypt 的源代码,这应该是正在生成的 key (\0 填充),但它根本不会接受它。

理论上,PHP pack('a32', 'my Secret key'); 应该会产生与 PHP 的 mcrypt 生成的相同的\0 填充 key ,但事实并非如此。

我非常接近再次加密所有内容,但使用新 key 。这花费了太多时间。

最佳答案

问题不在于键的填充,而在于您使用了两种不同的 block 大小。在 PHP 中,使用 MCRYPT_RIJNDAEL_256 使用的 block 大小为...256 位。然而,在使用 Crypt::Rijndael 的 Perl 中,他们注意到:

blocksize
The blocksize for Rijndael is 16 bytes (128 bits), although the algorithm actually supports any blocksize that is any multiple of our bytes. 128 bits, is however, the AES-specified block size, so this is all we support.

因此没有 key 可以允许在这些不同算法之间进行转换。您可以在 PHP 中切换到 128 位:

<?
$key = "abcdefghijklmnopqrstuvwxyz";
$data = "Meet me at 11 o'clock behind the monument.";
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_ECB, nil);
echo bin2hex($crypttext) . "\n";
// prints c613d1804f52f535cb4740242270b1bcbf85151ce4c874848fd1fc2add06e0cc2d26b6403feef4a8df18f7dd7f8ac67d
?>

哪个 Perl 可以使用 Crypt::Rijndael 毫无问题地解密:

use Crypt::Rijndael;
$key = "abcdefghijklmnopqrstuvwxyz\0\0\0\0\0\0";
$crypttext = "c613d1804f52f535cb4740242270b1bcbf85151ce4c874848fd1fc2add06e0cc2d26b6403feef4a8df18f7dd7f8ac67d";
$cipher = Crypt::Rijndael->new($key, Crypt::Rijndael::MODE_ECB());
print $cipher->decrypt(pack('H*', $crypttext));
# prints "Meet me at 11 o'clock behind the monument."

或者您可以切换到支持更多 block 大小的不同 Perl 模块,例如 Crypt::Rijndael_PP :

# Same PHP code except using MCRYPT_RIJNDAEL_256
# prints f38469ec9deaadbbf49bb25fd7fc8b76462ebfbcf149a667306c8d1c033232322ee5b83fa87d49e4e927437647dbf7193e6d734242d583157b492347a2b1514c

Perl:

use Crypt::Rijndael_PP ':all';
$key = "abcdefghijklmnopqrstuvwxyz\0\0\0\0\0\0";
$crypttext = "f38469ec9deaadbbf49bb25fd7fc8b76462ebfbcf149a667306c8d1c033232322ee5b83fa87d49e4e927437647dbf7193e6d734242d583157b492347a2b1514c";
print rijndael_decrypt(unpack('H*', $key), MODE_ECB, pack('H*', $crypttext), 256, 256);
# prints "Meet me at 11 o'clock behind the monument."

关于php - 找出 PHP 的 mcrypt 创建的确切 key ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11540924/

相关文章:

php - 有什么方法可以检查迁移是否结束

php - symfony 功能测试的 500 状态代码

php - 使用 Rijndael 进行不同的 Delphi/PHP 加密解密

php - 使用 Go 和 PHP 进行 AES 加密

php - Lucene/Sphinx/Solr 是如何工作的?

javascript - 如何在PHP中的特定时间使用不同的变量

javascript - 使用 PHP mcrypt 加密后使用 Javascript CryptoJS 解密 AES

javascript - 使用 CryptoJS 加密并使用 PHP 解密

php - 如何使用dcpcrypt在delphi和php之间同步加密

c++ - Linux 的 Rijndael 替代品