计算由PHP的mcryp创建的确切密钥

2024-05-14 23:37:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在维护的一个PHP应用程序使用Rijndael_256和EBC_模式加密和mcrypt。有趣的是,密钥不是256位长,而是只有160位长。根据^{}文档,如果密钥太小,则用\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 = 'abcdefghijkm';,它太短了,但是PHP的mcrypt实现确保在使用RIJNDAEL_时将其扩展到32个字符(或256位)。最后一把钥匙会是什么样子?在

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

更新

使用Perl,我可以生成一个填充了pack('a32', 'my secret key');(或Z32)的密钥,length()将报告32,并且{}模块接受该密钥。看一下PHP的mcrypt的源代码,这应该是生成的密钥(\0 padded),但它不能接受它。在

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

我很快就可以再次加密所有东西了,但是要用一个新的密钥。这太花时间了。在


Tags: the数据key应用程序ismywith密钥
2条回答

\0是'00'的十六进制值! 所以我测试了3个代码,它们返回的都是一样的:)

  1. 让mcrypt_encrypt加密做'\0'填充
  2. 添加了PHP空值
  3. 添加了PHP转换的0个十六进制值

代码:

function encryptThis($text,$key){
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv);
    return ($crypttext);
}

echo bin2hex(encryptThis("Meet me at 11 o'clock behind the monument.", "abcdefghijklmnopqrstuvwxyz"))."<br/>";

echo bin2hex(encryptThis("Meet me at 11 o'clock behind the monument.", "abcdefghijklmnopqrstuvwxyz" . NULL . NULL . NULL . NULL . NULL . NULL))."<br/>";

echo bin2hex(encryptThis("Meet me at 11 o'clock behind the monument.", "abcdefghijklmnopqrstuvwxyz" . hex2bin(0) . hex2bin(0) . hex2bin(0) . hex2bin(0) . hex2bin(0) . hex2bin(0)))."<br/>";

?>

问题不是键的填充,而是你使用了两种不同的块大小。在PHP中,使用MCRYPT_RIJNDAEL_256使用的块大小为。。。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.

所以没有密钥可以在不同的算法之间进行转换。您可以在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解密而不出问题:

^{pr2}$

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

相关问题 更多 >

    热门问题