计算PHP创建的确切密钥';s mcrypt

计算PHP创建的确切密钥';s mcrypt,php,mcrypt,rijndael,Php,Mcrypt,Rijndael,我维护的一个PHP应用程序使用Rijndael_256和带有mcrypt的EBC_模式加密。有趣的是,密钥不是256位长,而是只有160位。根据文档,如果密钥太小,则会用\0填充该密钥以获得所需的大小 用于加密数据的密钥。如果它小于 所需的密钥大小,用“\0”填充。最好不要使用 键的ASCII字符串 这似乎发生在第1213行的开始和修改关键点附近 假设我们有$key='abcdefghijkm'太短,但PHP的mcrypt实现确保在使用RIJNDAEL_256时将其扩展到32个字符(或256位)

我维护的一个PHP应用程序使用Rijndael_256和带有mcrypt的EBC_模式加密。有趣的是,密钥不是256位长,而是只有160位。根据文档,如果密钥太小,则会用\0填充该密钥以获得所需的大小

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

这似乎发生在第1213行的开始和修改关键点附近

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

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

更新

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

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


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

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

  • 让mcrypt_encrypt执行“\0”填充
  • 添加了PHP空值
  • 添加了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/>";
    
    ?>
    
    函数加密此($text,$key){
    $iv_size=mcrypt_get_iv_size(mcrypt_RIJNDAEL_256,mcrypt_MODE_ECB);
    $iv=mcrypt\u create\u iv($iv\u大小,mcrypt\u兰德);
    $crypttext=mcrypt_encrypt(mcrypt_RIJNDAEL_256,$key,$text,mcrypt_MODE_ECB,$iv);
    返回($文本);
    }
    echo bin2hex(加密此(“11点在纪念碑后面见我。”,“abcdefghijklmnopqrstuvwxyz”)。“
    ”; echo bin2hex(加密此(“11点在纪念碑后面见我。”,“abcdefghijklmnopqrstuvwxyz.NULL.NULL.NULL.NULL.NULL”)。“
    ”; echo bin2hex(加密此(“11点在纪念碑后面见我。”,“abcdefghijklmnopqrstuvwxyz”)。hex2bin(0)。hex2bin(0)。hex2bin(0)。hex2bin(0)。hex2bin(0)。hex2bin(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
    ?>
    
    或者,您可以切换到支持更多块大小的不同Perl模块,例如:

    Perl:


    你试过用0填充它吗?是的,但是运气不好。记住,结果可能不是可打印的字符,所以不要依赖控制台/页面输出来确定键的实际外观。但是,如果您将生成的密钥写入二进制文件,您应该能够将其拉入您的perl脚本并成功使用它。我正在使用已使用PHP的
    mcrypt_encrypt
    加密的纯文本进行尝试,并尝试使用perl的
    Crypt::Rijndael
    进行解密。我需要知道的是,当PHP的
    mcrypt_encrypt
    使用它时,实际的密钥是什么样子的:-)。请原谅我没有直接回答这个问题,但我认为这是个坏主意。如果您的密钥是密码,请首先使用KDF(例如PBKDF2、bcrypt、scrypt)扩展您的值,然后使用结果加密数据。我很高兴让
    mcrypt\u encrypt
    进行\0填充。我需要确切的密钥,以便在另一种编程语言中使用它。谢谢你提到0x00,我忘了那个。不知道perl的
    undef
    是否相同(怀疑是否相同)。它必须是32个字符。在本例中,字母表是26,32-26=6,因此必须添加6个空值或0x00:)现在格式混乱。实际上,
    $key1
    $key2
    的长度完全相同,因此
    mcrypt_encrypt
    仍在处理填充。这同样适用于
    $key3
    。因此,它们给出相同的结果也就不足为奇了,因为对于PHP,它们都包含
    “abcdefghijklmnopqrstuvwxyz”
    。因此最后一个键是
    “abcdefghijklmnopqrstuvwxyz”。无效的无效的无效的无效的无效的无效
    …因为
    strlen()
    以字节为单位计算字符串的长度,所以我希望它也计算\0,因为这也是一个字节。因为我们还不能确定在mcrypt修改键字符串之前PHP对字符串做了什么,所以仍然不能确定字符串最终应该是什么样子。谢谢,我已经开始认为blocksize与此有关,但还没有时间检查它。我想我将使用
    Crypt::Rijndael_PP
    那么。嗯,虽然
    $key
    实际上是256位长
    Crypt::Rijndael_PP
    仍然在它后面附加0。在我看来里面好像有个bug?@Htbaa
    Crypt::Rijndael_PP
    不像
    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."
    
    # Same PHP code except using MCRYPT_RIJNDAEL_256
    # prints f38469ec9deaadbbf49bb25fd7fc8b76462ebfbcf149a667306c8d1c033232322ee5b83fa87d49e4e927437647dbf7193e6d734242d583157b492347a2b1514c
    
    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."