Java代码Cipher.doFinal(byte[])的JavaScript/NodeJS等效代码是什么?

3
我正在将一些服务器端Java代码迁移到新的NodeJS服务器。我正在寻找与Java的Cipher.doFinal(byte[])相等的Javascript方法调用。请注意,我不能使用NodeJS Buffers,因为它们不支持负字节值。因此,为了进行加密,我需要一个接受正数和负数数组的方法。
这是我目前与此问题相关的所有内容:
NodeJS / Javascript: var crypto = require('crypto'); var cipher = crypto.createCipher('aes256',key);
Java (javax.crypto.Cipher):
Cipher cipher;
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
try {
    cipher = Cipher.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
} catch (NoSuchPaddingException e) {
}try {
      cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
} catch (InvalidKeyException e) {
}

在Java代码中,我调用了这个方法,其中Iv代表初始化向量:byte[] newIv = cipher.doFinal(myIv); 我该如何在JavaScript中得到与doFinal Java方法相同的结果?
2个回答

3

字节处理

你可以使用NodeJS的缓冲区。Java中的字节数组可能只包含有符号字节,但是这些字节与无符号字节没有任何区别。只有实际位的值才是重要的。如果您需要直接处理字节,通常最好使用十六进制。您可以通过执行b & 0xFF来将其转换为正整数值,您可以通过执行(byte) b来进行相反的操作。

当然,您也可以在NodeJS中执行类似操作,使其处理有符号数字,但是将密钥、IV等视为无符号是常见的做法。

密码选择

对于Java AES加密,您正在使用不安全的"AES/ECB/PKCS5Padding"模式,因为Oracle Java JCE提供程序默认使用ECB模式加密和PKCS#7填充(由Java错误地命名为"PKCS5Padding")。ECB不使用IV,因此您可以忽略IV的值。令人奇怪的是,您必须使用crypto.createCipheriv(algorithm, key, iv),因为crypto.createCipher(algorithm, password)使用密码而不是密钥。当然,如果您的密钥确实是256位大小,则还应该在NodeJS/OpenSSL中使用算法"AES-256-ECB"


我省略了对NodeJS密码流的实际编写。一旦您创建了正确的算法和密钥,这应该相对简单。如果您需要传输层安全性,则应迁移到更安全的协议(首选TLS)。 - Maarten Bodewes
我认为我的代码中有一些区域,在负字节(有符号字节)上进行位操作时,与它们的无符号版本不同。在JS中不能将其转换为字节。我该如何让NodeJS处理有符号数字?我正在为游戏使用特定的AES自定义加密算法,这两个都是我在网上找到的。与此AES相关联的IV长度为4个字节,所以var cipher = crypto.createCipheriv('aes256',key,iv); 返回无效的IV长度... 此外,这个AES要求我定期刷新IV,就像上面的“newIv”Java代码一样,我需要在JS中实现。 - Omnipotence
我正在尝试出于教育目的,用Javascript/Node编写别人的服务器代码。具体来说,我正在尝试编写此类中的加密方法 https://xp-dev.com/svn/MapleGame/Common/Security/AesCryptograph.cs - Omnipotence
甚至在Java类中的同一方法中:http://svn6.assembla.com/svn/MoopleDEV/src/tools/MapleAESOFB.java 如果你想知道,我正在为一个旧的MMORPG客户端制作服务器,所以有一些在线资源。 - Omnipotence
这个答案有帮助,但并没有完全回答问题。对于我这个 NodeJS 新手来说,实际写入到节点加密流中不容易弄清楚。在你帮助新手的时候,越深入越好 :) - Omnipotence
显示剩余4条评论

2

原来你可以这样放置一个空的IV:

var cipher = require('crypto').createCipheriv('aes-256'ecb', key, '');

至于替换方法,只需临时将旧IV存储为新IV,然后尝试使用旧IV更新该新IV。以下是使用缓冲区创建的Initialization Vectors的一些NodeJS代码示例:
var newIV = oldIV.slice(); newIV = cipher.update(newIV); oldIV = newIV;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接