Node.js Crypto AES密码

出于某种奇怪的原因,Node的内置CipherDecipher类没有按预期工作。 该文档指出cipher.update

“返回encryption的内容,并且在stream式传输时可以使用新数据多次调用。”

该文件还声明cipher.final

“返回任何剩余的encryption内容。”

但是,在我的testing中,您必须调用cipher.final来获取所有数据,从而使Cipher对象变得毫无价值,并且要处理下一个块,您必须创build一个新的Cipher对象。

 var secret = crypto.randomBytes(16) , source = crypto.randomBytes(8) , cipher = crypto.createCipher("aes128", secret) , decipher = crypto.createDecipher("aes128", secret); var step = cipher.update(source); var end = decipher.update(step); assert.strictEqual(source.toString('binary'), end); // should not fail, but does 

请注意,这发生在使用crypto.createCiphercrypto.createCipheriv ,秘密作为初始化向量。 解决办法是用下列内容replace第6行和第7行:

 var step = cipher.update(source) + cipher.final(); var end = decipher.update(step) + decipher.final(); 

但是,如前所述,这使cipherdecipher变得毫无价值。

这就是我期望Node的内置encryption技术能够工作,但显然不是。 这是如何使用它或节点中的错误的问题? 还是我期待错误的事情? 我可以直接执行AES,但是这样做会很耗时和烦人。 每当我需要encryption或解密时,是否应该创build一个新的CipherDecipher对象? 如果我这样做是一个stream的一部分,这似乎很昂贵。

我遇到了两个问题:第一个是我错误地认为块的大小是64位,或8字节,这是我用来创build“明文”的。 实际上,AES的内部将128位明文分成两个64位块,然后从这里开始。

第二个问题是,尽pipe在应用上述更改后使用正确的块大小, crypto模块应用了自动填充,禁用自动填充解决了第二个问题。 因此,工作实例如下:

 var secret = crypto.randomBytes(16) , source = crypto.randomBytes(16) , cipher = crypto.createCipheriv("aes128", secret, secret); // or createCipher , decipher = crypto.createDecipheriv("aes128", secret, secret); cipher.setAutoPadding(false); decipher.setAutoPadding(false); var step = cipher.update(source); var end = decipher.update(step); assert.strictEqual(source.toString('binary'), end); // does not fail 

AES使用16个字节的块大小(不是您build议的8倍)。 而且,如果启用填充,它应该始终填充。 其原因是,否则,非压缩algorithm不能区分填充和明文的最后字节。

大多数情况下,您不应该期望密文与纯文本的大小相同。 确保始终调用doFinal() 。 如果您正在实现自己的encryptionscheme,则只应使用此方法进行encryption/解密。

有一个node.js连续多次调用更新的问题 。 我想这个问题已经解决,并在下一个版本中反映出来。