【问题标题】:Porting AES Java decipher code to Node.js将 AES Java 解密代码移植到 Node.js
【发布时间】:2014-03-06 11:46:06
【问题描述】:

我想将以下 Java 代码移植到 Node.js:

// Java

byte[] rawKey = "deadbeefdeadbeef".getBytes("us-ascii");
SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cip = Cipher.getInstance("AES/ECB/NoPadding");
cip.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] plaintext = cip.doFinal(ciphertext, 0, ciphertext.length);

这是我对 Node.js 的尝试,使用流

// JS, using the crypto streams API

var decipher = crypto.createDecipher('aes-128-ecb', 'deadbeefdeadbeef');
decipher.setAutoPadding(false);
decipher.pipe(concat(function(plaintext) { console.log(plaintext); });
decipher.end(ciphertext);

而且,还有一个 Node.js 尝试使用旧的 .update().final() API:

// JS, using the `.update()` and `.final()` API

var decipher = crypto.createDecipher('aes-128-ecb', 'deadbeefdeadbeef');
decipher.setAutoPadding(false);
var pieces = [];
pieces.push(new Buffer(decipher.update(ciphertext)));
pieces.push(new Buffer(decipher.final()));
var plaintext = Buffer.concat(pieces);

这两个版本都生成正确长度的相同输出(与输入的长度相同),但此输出与 Java 版本的解密器在同一输入缓冲区上运行时生成的明文不同。如何像上面配置的 Java 解密那样设置 Node.js 解密?

谢谢。

【问题讨论】:

  • 您似乎在 Java 代码中使用 AES-128,而您在 JS 代码中指定 AES-256。我不确定 JS API 如何接受 256 位密码的 128 位密钥;也许它正在执行某种密钥派生?
  • 我的错,那是旧代码的复制/粘贴!谢谢你指出来。在发布这个问题的时候,我已经想出了很多。我已经解决了这个问题,并将很快发布答案。虽然,我不精通加密,也不明白答案的含义:使用crypto.createDecipheriv('aes-128-ecb', 'deadbeefdeadbeef', ''); 成功了。
  • @ntoskrnl:是的,有一段时间我使用带有 128 位密钥的 aes-256-ecb,它没有抛出或指示错误。只是产生不想要的解密输出。
  • @dimadima 由于您的密文不受完整性或真实性保护,您的密文将愉快地解密为随机字节。通常这会被 unpadding 捕获(由于 padding oracle 攻击,它本身可能会产生灾难性的结果),但否则输出只是随机的。您甚至可以使用 DES 解密并获得结果。添加 MAC 或 HMAC 以防止此类事情发生(并使用 CBC 和填充,您当前的解决方案可能在许多层面上都不安全)。
  • decipher.pipe(concat(...中的concat函数是什么?

标签: java javascript node.js encryption cryptography


【解决方案1】:

createDecipher 实际上并不像在 Java 中那样使用密钥。它使用密码,该密码被输入基于密码的密钥派生函数 (PBKDF) 以 派生 密钥。因此,使用不同的密钥并且没有检查密钥正确性的方法,您将获得随机纯文本。

Node.js API 的命名不是很好,函数createDeciphercreateDecipheriv 表明后者与前者相同,只是增加了一个IV。相反,createDecipher 将整个密钥派生函数添加到组合中。

【讨论】:

  • @dimadima 为您解答,如果您不介意的话,因为我知道为什么这会产生如此大的不同。请说明您是否对代码进行了其他更改以使其正常工作。
  • 非常感谢。是的,只需更改为 IV 功能即可。具体来说:crypto.createDecipher('aes-128-ecb', 'deadbeefdeadbeef') -> crypto.createDecipheriv('aes-128-ecb', 'deadbeefdeadbeef', '')
  • 如果我使用建议的解决方案,v0.10.35 节点总是抛出错误“node-crypto : Invalid IV length” - 任何解决方法?
  • @Skomski 尝试使用crypto.randomBytes(size) 创建 IV,确保您了解 NodeJS 处理缓冲区和流式传输的方式。 IV可以作为密文的前缀。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多