【发布时间】: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