Node.js加密AES密码

时间:2012-08-22 05:54:34

标签: node.js aes encryption

由于某些奇怪的原因,Node的内置CipherDecipher类无法正常工作。 documentation表示cipher.update

  

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

docs也声明cipher.final

  

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

但是,在我的测试中,你必须调用cipher.final来获取所有数据,从而使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时会发生这种情况,并将秘密作为初始化向量。修复是用以下代码替换第6行和第7行:

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

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

这就是我期望Node的内置加密工作的方式,但显然不是这样。这是我如何使用它或Node中的错误的问题?或者我期待错误的事情?我可以直接实施AES,但这将是耗时且烦人的。我是否应该在每次需要加密或解密时创建一个新的CipherDecipher对象?如果我作为流的一部分这样做,这似乎很昂贵。

3 个答案:

答案 0 :(得分:3)

我遇到了两个问题:首先是我错误地假设一个块的大小是64位,或者是8个字节,这就是我用来创建“明文”的问题。实际上,AES的内部将128位明文分成两个64位块,并从那里开始。

第二个问题是,尽管在应用上述更改后使用了正确的块大小,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

答案 1 :(得分:2)

AES使用16字节的块大小(不是您建议的两倍8)。此外,如果填充已启用,则应始终填充。原因是否则unpadding算法无法区分填充和明文的最后一个字节。

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

答案 2 :(得分:0)

连续多次调用更新a node.js issue。我想它已在下一个版本中得到解决和反映。