加密结果在PHP和Node.js中有所不同

时间:2017-02-11 07:57:51

标签: php node.js encryption

我正在使用AES 128 CBC加密字符串“aaaaaaaaaaaaaaa”(一个16字节的UTF8字符串),带有空白的iv和键(16 0)并得到不同的结果

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'

我承认我对这里发生的事情感到非常不稳定 - 我在这里错过了什么?

编辑 ...但不是那么不稳定我不明白我在这里所做的并不是特别安全。不要担心这是否是加密的“正确”方式 - 请关注结果应该排列的事实。

edit2 - 但是,我可以使用十六进制而不是base64来接近 -

PHP:926c0fea05afd65f5931d29a9c6b3f9c

节点: 926c0fea05afd65f5931d29a9c6b3f9c 779489d69ef19e1d2b41d4ee9db3fb57

.final方法返回第二个Node十六进制块,我不明白它的用途。

1 个答案:

答案 0 :(得分:4)

AES的块大小为16字节。您正在加密字符串" hello world",它在UTF8中长度为11个字节。因此,填充用于将字符串的长度增加到16个字节。

Node,并且应该使用PKCS5 Padding将纯文本填充到16个字节,然后对其进行加密。

mcrypt,因为不应该,使用零字节来填充纯文本。 mcrypt 已弃用,已被放弃了十年。

因为你的两个填充方案不同,所以在我们应用AES之前,纯文本实际上是不同的。

我的建议:改用PHP中的openssl_*函数。并且不要使用静态IV。使用静态IV会使您的程序容易受到与ECB模式相同的一些漏洞的攻击,这不是很好!