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模式相同的一些漏洞的攻击,这并不好!