编辑:我的问题已经更新,请查看这篇文章的底部以了解最新一期。我把剩下的留给想阅读整个故事的人:)
我一直致力于将一个小型 Java 应用程序转换为 Node.js,这在很大程度上进展顺利。我不得不查找大量 Java 函数来弄清楚它们的作用以及如何在 Node 中复制它们的行为(因为我几乎没有任何 Java 经验),但我现在已经掌握了大部分功能。
不幸的是,有一点我似乎无法开始工作。它是一种用于生成密码哈希的方法,使用了一组在 Node.js 中似乎不存在的高级 Java 特定函数。我已经尝试了两天来让它工作,但我就是无法获得我想要的结果。
这是原始 Java 代码:
public static String hashPassword(final String password, final String salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
final char[] passwordChars = password.toCharArray();
final byte[] saltBytes = salt.getBytes();
final PBEKeySpec spec = new PBEKeySpec(passwordChars, saltBytes, 1000, 192);
final SecretKeyFactory key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
final byte[] hashedPassword = key.generateSecret(spec).getEncoded();
return String.format("%x", new BigInteger(hashedPassword));
}
注意:salt是固定值,不是随机的。我知道这不应该是这样,但这是应用程序的设置方式。因此,由于 Java 代码总是得到相同的结果,因此在 Node 中也应该可以得到相同的结果。
我尝试过使用 crypto.pbkdf2
,使用各种看似相似的密码,但它们都给了我与 Java 代码不同的结果。所以我想我会在这里问,看看是否有人知道如何做到这一点,或者对如何处理这个问题有任何建议。
请注意(正如我所说)我对 Java 一无所知,所以我很难让它工作可能是因为我很难掌握这个方法中发生的事情,并用谷歌搜索使用的各种功能给出了相互矛盾的答案,而且大多只是表明其他人也很难与他们相处。
所以实际上我要问三个问题:
- 这是否可以在 Node.js 中复制,或者 Java 是否使用了 Node 中不存在的功能?
- 有更多 Java 经验的人可以解释这段代码中的各行,以及每一行的作用吗?最好是具有一定水平的 Node.js 经验(和一些 PHP)但从未使用过 Java 的人会理解:)
- 如果有人知道,我要查看哪些 Node 函数才能使其正常工作?我可以使用内置的加密模块来实现吗,还是需要额外的模块?
最后,在你说“只实现一个特定于 Node 的哈希算法”(这将是更简单的选择)之前,我不能这样做,因为这将用于已经包含这些哈希密码的现有数据库,并且也被其他现有的 Java 应用程序使用。目前无法更改其他应用程序或数据库。
更新:我得到了一个非常有帮助的答案,现在我在我的 Node.js 代码中得到了这个:
hashPassword = function(password, salt){
crypto.pbkdf2(password, new Buffer(salt), 1000, 24, 'sha1', function(err, key){
}
}
这就是我再次陷入困境的地方。我无法从键中获取我需要的字符串值。我用谷歌搜索了一下,发现 Java 代码中的 String.format
行将 BigInteger 转换为十六进制整数,但我似乎无法获得正确的值。
- 我简单地尝试了
key.toString('hex')
但那没有用。 - 我找到了这个 node-biginteger模块,并尝试了
BigInteger.fromBuffer(1, key).toString(24)
和一些变体,但它仍然给我一个与 Java 应用程序截然不同的结果。
非常感谢任何有关如何从缓冲区中获取正确字符串值的帮助。
Update2:我终于让我的应用程序运行起来了,事实证明它是一个输出错误哈希值的外部模块。正确实现加密模块修复了它。
最佳答案
这些参数生成相同的缓冲区:
crypto.pbkdf2('test', 'salt', 1000, 24, 'sha1', function(err, key) {});
剩下的就是用同样的方式格式化一个字符串。这可能有点问题,因为 BigInteger
是有符号的,所以你也应该考虑到符号。
您可以使用 bn.js 执行以下操作:
function format(key) {
if (key[0] >>> 7 === 0) {
return key.toString('hex');
}
return '-' + new BN(key.toString('hex'), 16).notn(192).add(new BN(1)).toString(16);
}
bn.js 不会将前导位解释为符号,所以你必须先检查它,然后根据 two's complement 转换为字符串。代表。
关于javascript - 在 Node.js 中复制 Java 密码哈希代码 (PBKDF2WithHmacSHA1),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34462316/