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


  用来加密数据的密钥。如果小于
  所需的密钥大小,用'\ 0'填充。最好不要使用
  密钥的ASCII字符串。


这似乎发生在line 1186 in mcrypt.c开头,并在第1213行修改了密钥。

因此,可以说我们的$key = 'abcdefghijkm';太短了,但是PHP的mcrypt实现可确保在使用RIJNDAEL_256时将其扩展为32个字符(或256位)。最终密钥是什么样的?

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

更新资料

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

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

我几乎要再次加密所有内容,但要使用新密钥。这花费了太多时间。

最佳答案

问题不是密钥的填充,而是您使用的是两种不同的块大小。在PHP中,使用MCRYPT_RIJNDAEL_256使用的块大小为256位。但是,在使用Crypt::Rijndael的perl中,他们指出:


  块大小
  Rijndael的块大小为16个字节(128位),尽管该算法实际上支持任何字节大小的块大小。但是,128位是AES指定的块大小,因此这就是我们支持的全部。


因此,没有密钥可以在这些不同算法之间进行转换。您可以在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
?>


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

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."


或者,您可以切换到支持更多块大小的其他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."

10-07 21:20