编辑:我的问题已更新,请查看此帖子底部的最新一期。我把剩下的人留给想要阅读整个故事的人:)
我一直致力于将一个小型Java应用程序转换为Node.js,这在很大程度上一直很顺利。我必须查找很多Java函数来弄清楚它们的作用以及如何在Node中复制它们的行为(因为我几乎没有任何Java经验),但我现在已经完成了大部分功能。
不幸的是,有一点我似乎无法正常工作。它是一种用于生成密码哈希的方法,使用一组在Node中似乎不存在的高级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));
}
注意:盐是固定值,它不是随机的。我知道这不应该是这样,但这就是应用程序的设置方式。因此,由于Java代码总是得到相同的结果,因此应该可以在Node中获得相同的结果。
我尝试使用crypto.pbkdf2
,使用看似相似的各种密码,但这些都给了我与Java代码不同的结果。所以我想我会问这里,看看是否有人知道该怎么做,或者对如何处理这个问题有任何建议。
请注意(正如我所说)我不了解Java的问题,所以让我这么做的困难可能来自这样一个事实:我很难掌握这个方法中发生的事情,并且谷歌搜索所使用的各种函数给出了相互矛盾的答案,而且大多数只是表明其他人也很难用它们。
所以我实际上有三个问题要求:
最后,在你说“只实现一个特定于节点的散列算法”之前(这将是更容易的选择),我不能这样做,因为这将用于已经包含这些散列密码的现有数据库也被其他现有的Java应用程序使用。目前无法更改其他应用程序或数据库。
更新:我得到了一个非常有用的答案,现在我在我的Node.js代码中得到了这个:
hashPassword = function(password, salt){
crypto.pbkdf2(password, new Buffer(salt), 1000, 24, 'sha1', function(err, key){
}
}
那就是我再次陷入困境的地方。我无法从密钥中获取所需的字符串值。我用google搜索了一下,发现Java代码中的String.format
行将BigInteger转换为十六进制整数,但我似乎无法得到正确的值。
key.toString('hex')
但是没有用。BigInteger.fromBuffer(1, key).toString(24)
及其中的一些变体,但它仍然给我一个与Java应用程序截然不同的结果。非常感谢有关如何从缓冲区获取正确字符串值的任何帮助。
Update2 :我终于让我的应用程序工作了,因为事实证明它是一个输出坏哈希的外部模块。实现加密模块正确修复它。
答案 0 :(得分:2)
这些参数生成相同的缓冲区:
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表示转换为字符串。
答案 1 :(得分:0)
我需要让它与节点6一起工作,事实证明,事情变得更简单(不需要bigints)。但是,如果没有vkurchatkin的原始答案,我绝不会想到这一点:
console.log(hashPassword('password', 'salt').toString('hex'));
function hashPassword(password, salt) {
return crypto.pbkdf2Sync(password, Buffer.from(salt, 'hex'), 1000, 24, 'sha1');
}