PHP和Node.js的encryption结果不同
我使用AES 128 CBC以空白iv和键(16 0)对string“aaaaaaaaaaaaaaaaaa”(一个16字节的UTF8string)进行encryption,得到不同的结果
在PHP中:
echo base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128,pack("H*", "00000000000000000000000000000000"),"aaaaaaaaaaaaaaaa",MCRYPT_MODE_CBC,pack("H*", "00000000000000000000000000000000")))
返回“kmwP6gWv1l9ZMdKanGs / nA ==”
在Node.js中:
let cipher = require('crypto').createCipheriv('aes-128-cbc',Buffer.alloc(16),Buffer.alloc(16)) console.log(cipher.update('aaaaaaaaaaaaaaaa','utf8','base64') + cipher.final('base64'))
返回“ kmwP6gWv1l9ZMdKanGs / n HeUidae8Z4dK0HU7p2z + 1c =”
第一位(粗体)与PHP相同,但PHP值有一个额外的'A =',然后Node值有一个额外的'HeUidae8Z4dK0HU7p2z + 1c'
我承认我在这里发生了什么事情 – 我在这里错过了什么?
编辑 …但不是那么不稳定,我不明白,我在这里做什么是不是特别安全。 不要担心这是否是“正确的”encryption方式,请注意结果应该一致。
edit2 – 然而,我可以使用hex而不是base64closures –
PHP:926c0fea05afd65f5931d29a9c6b3f9c
节点: 926c0fea05afd65f5931d29a9c6b3f9c 779489d69ef19e1d2b41d4ee9db3fb57
第二个节点hex块是由.final方法返回的,我不明白它是什么。
AES在16字节的块大小上工作。 您正在encryptionstring“hello world”,它是UTF8中的11个字节长。 因此,使用填充将string的长度增加到16个字节。
节点,并且应该使用PKCS5 Padding将纯文本填充到16个字节,然后对其进行encryption。
mcrypt,因为它不应该使用零字节来填充你的纯文本。 mcrypt被弃用 ,并被放弃了十年。
因为你的两个填充scheme是不同的,所以在我们甚至到达应用AES的点之前,纯文本实际上是不同的。
我的build议是:在PHP中使用openssl_*
函数。 并且不要使用静态IV。 使用静态IV会使您的程序容易受到与ECB模式相同的一些漏洞的攻击,这并不好!