Node.js aes128加密/解密端口到PHP

时间:2012-11-15 07:49:14

标签: php node.js encryption openssl aes

所以在node.js中,我有一个使用aes128的加密方案而没有通过IV。一个例子是以下

 var cipher = require('crypto').createCipher('aes128','password');
 cipher.update('test','utf8','base64')+cipher.final('base64');

输出CjZ3R/tW8jiyLvg+/TE6bA==。问题是我无法在PHP中重现这一点,即使我已经尝试了一堆实现和变体。

当我尝试通过openssl运行时,我运行以下命令:

 echo "test" | openssl enc -e -aes128 -a -k password

输出U2FsdGVkX19Ccfv3SWvuzuZWeov9GDuwx1RMK2HWa / s =也与之匹配。我也尝试将-md与所有可能的选项一起使用,并且两者都不匹配(它们甚至不是相同的块大小)。在PHP中运行时,我尝试使用填充来散列键/非散列,使用输入上的计算填充,其中填充字符是所需填充字符的数量(在网上看到这是nodejs使用的内容)。我已经尝试将IV设置为密码并且也设置为空字节,但仍然无法获得匹配。

这里有任何建议/想法吗?

编辑:

所以我刚刚在php中发现了函数openssl_encrypt并尝试了相同的测试并再一次得到了一个完全不同的输出(这个现在采用与node.js完全相同的args,并且据说他们都使用openssl):

 openssl_encrypt ( "test" , 'aes128' , "password")

哪个输出(已经在base64中)JleA91MvYHdEdnj3KYHmog==,它至少现在在块计数中匹配但仍然不是相同的密文。

我还应该提一下,将IV传递给nodejs是一个选项,可能会解决这个差异,但php中的这个方案将取代已经存在的nodejs中的旧方案,因此它必须能够解密已经创建的密文< / p>

1 个答案:

答案 0 :(得分:5)

所以我找到了解决方案。在查看node.js的c ++源代码后,我发现使用openssl函数EVP_BytesToKey生成了key和iv。在搜索了这个函数的实现之后,我发现了这个堆栈溢出帖子Encrypting data in Cocoa, decoding in PHP (and vice versa),它包含了这个函数的一个版本。修改它并添加openssl版本填充数据的事实,ascii字符等于填充所需的字节数我想出了以下函数,它完全匹配nodejs加密方案:

function aes128Encrypt($key, $data) {
    $padding = 16 - (strlen($data) % 16);
    $data .= str_repeat(chr($padding), $padding);

    $keySize   = 16;
    $ivSize    = 16;

    $rawKey = $key;
    $genKeyData = '';
    do
    {
        $genKeyData = $genKeyData.md5( $genKeyData.$rawKey, true );
    } while( strlen( $genKeyData ) < ($keySize + $ivSize) );

    $generatedKey = substr( $genKeyData, 0, $keySize );
    $generatedIV  = substr( $genKeyData, $keySize, $ivSize );

    print($generatedIV);
    print($generatedKey);

    return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $generatedKey, $data, MCRYPT_MODE_CBC, $generatedIV);
}

与node.js函数完全匹配:

 function aes128Encrypt(key,data) {
      var cipher = require('crypto').createCipher('aes128',key);
      return cipher.update(data,'utf8','binary')+cipher.final('binary');
 }