编辑:我的问题已更新,请查看此帖子底部的最新一期.我把剩下的人留给想要阅读全文的人:)
我一直在努力将一个小型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的内容,所以我将这个问题付诸实践的困难可能来自于我很难掌握这个方法中发生的事情,以及谷歌搜索所使用的各种函数给出了相互矛盾的答案,并且大多只是表明其他人也很难与他们相处.
所以我实际上有三个问题要问:
>这可以在Node.js中复制,还是Java使用Node中不存在的功能?
>具有更多Java经验的人是否可以解释此代码中的各个行,以及每个行的作用?最好是以某种程度的Node.js体验(和一些PHP),但从未使用过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’),但这不起作用.
>我找到了这个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表示转换为字符串.