javascript - 在 Node.js 中复制 Java 密码哈希代码 (PBKDF2WithHmacSHA1)

标签 javascript java node.js hash pbkdf2

编辑:我的问题已经更新,请查看这篇文章的底部以了解最新一期。我把剩下的留给想阅读整个故事的人:)

我一直致力于将一个小型 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 一无所知,所以我很难让它工作可能是因为我很难掌握这个方法中发生的事情,并用谷歌搜索使用的各种功能给出了相互矛盾的答案,而且大多只是表明其他人也很难与他们相处。

所以实际上我要问三个问题:

  1. 这是否可以在 Node.js 中复制,或者 Java 是否使用了 Node 中不存在的功能?
  2. 有更多 Java 经验的人可以解释这段代码中的各行,以及每一行的作用吗?最好是具有一定水平的 Node.js 经验(和一些 PHP)但从未使用过 Java 的人会理解:)
  3. 如果有人知道,我要查看哪些 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/

相关文章:

javascript - 如何使用 Node.js 将变量传递给 Jade 中的页脚

javascript - Jquerymobile - 展开/折叠全部按钮

java - 如何让文本字段水平填充 100%

java - For 循环检查字符串是否包含符号?

java - 我正在使用 spring-reactor 丢失消息,我的设置有什么问题?

javascript - Mocha 单元测试路由返回 200 ok

node.js - 将 Postgres 与新创建的 React 应用程序一起使用时出错 : Module not found: Can't resolve 'dns'

javascript - 当我进行拖动操作时,D3 表现得很奇怪,这也触发了意外的缩放功能

javascript - 如何随 promise 一起返回数据

javascript - 在 url 中传递查询的安全性如何