use*_*563 1 php encryption openssl aes node.js
所以在node.js中我有一个使用aes128的加密方案而没有通过IV.以下是一个例子
var cipher = require('crypto').createCipher('aes128','password');
cipher.update('test','utf8','base64')+cipher.final('base64');
Run Code Online (Sandbox Code Playgroud)
哪个输出CjZ3R/tW8jiyLvg+/TE6bA==.问题是我无法在PHP中重现这一点,即使我已经尝试了一堆实现和变体.
当我尝试通过openssl运行时,我运行以下命令:
echo "test" | openssl enc -e -aes128 -a -k password
Run Code Online (Sandbox Code Playgroud)
输出U2FsdGVkX19Ccfv3SWvuzuZWeov9GDuwx1RMK2HWa/s =也是不匹配的.我也试过使用-md所有可能的选项,但也不匹配(它们甚至不是相同的块大小).在PHP中运行时,我尝试使用填充来散列键/非散列,使用输入上的计算填充,其中填充字符是所需填充字符的数量(在网上看到这是nodejs使用的内容).我已经尝试将IV设置为密码并且也设置为空字节但仍然无法获得匹配.
这里有什么建议/想法吗?
编辑:
所以我刚刚在php中发现了函数openssl_encrypt并尝试了相同的测试,并再次得到了一个完全不同的输出(这个现在与node.js完全相同的args,并且据说它们都使用openssl):
openssl_encrypt ( "test" , 'aes128' , "password")
Run Code Online (Sandbox Code Playgroud)
哪个输出(已经在base64中)JleA91MvYHdEdnj3KYHmog==至少现在在块计数中匹配但仍然不是相同的密文.
我还要提一下,是的,将一个IV传递给nodejs是一个选项,可能会解决这个差异,但是php中的这个方案将替换已经存在的nodejs中的旧方案,因此它必须能够解密已经创建的密文
所以我找到了解决方案.在查看了node.js的c ++源代码之后,我发现使用openssl函数EVP_BytesToKey生成了key和iv.在搜索了这个函数的实现后,我发现这个堆栈溢出在Cocoa中加密数据,在PHP中解码(反之亦然),其中包含此函数的一个版本.修改它并添加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);
}
Run Code Online (Sandbox Code Playgroud)
它与node.js函数完全匹配:
function aes128Encrypt(key,data) {
var cipher = require('crypto').createCipher('aes128',key);
return cipher.update(data,'utf8','binary')+cipher.final('binary');
}
Run Code Online (Sandbox Code Playgroud)