无法创建 Java 模拟 Java 方法的脚本,用于使用 SHA-256 和 salt 进行密码散列

Failed to create Javascript analog of Java method for password hashing using SHA-256 and salt

我已经为完成下一个目标而奋斗了一段时间: 我有一个应该向服务器发送新密码的 "Reset password" 页面。我想用盐对其进行哈希处理,以便最终将其保存在数据库中。在服务器端,我有下一个创建密码哈希的方法:

public static String makeHash(String password, String salt) {
    try {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(password.getBytes("UTF-8"));

        byte byteData[] = md.digest(makeHash(salt.toLowerCase()));

        return Base64.getEncoder().encodeToString(byteData);
    } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
        log.error("Unable to make hash for pass. No hashing.", e);
    }

    return password;
}

private static byte[] makeHash(String val) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    return MessageDigest.getInstance("SHA-256").digest(val.getBytes("UTF-8"));
}

我尝试了几个 Java 脚本库 - crypto、crypto-js、SJCL,但无法创建与 Java 方法生成的密码相同的密码。例如,最后的工作尝试是:

var crypto = require('crypto');
crypto.pbkdf2('123', 'test@gmail.com', 1000, 60, 'sha256', function(err, key) {
  if (err)
    throw err;
  console.log(key.toString('Base64'));  // 'c5e478d...1469e50'
});

它为我生成了这个哈希 - Qr2lzotlRWj7BeJeFooMRj64auMPTb3PRhwLmfNcl4DCVAlFFibgOqZiyExZNO5i/icAUYoMjy73jSTd,而 Java 为我生成了 - /pyQf3JCj5XoczfsYJ4LUb+y0DONGMl/AFzLiBTo8LA=

我无法更改后端,因为它 运行 已经有一段时间了,所以我希望有人可以帮助我解决这个问题。

你必须在两边使用相同的算法。在 Java 中,您仅使用 SHA-256,而在节点中,您使用带有 SHA-256 的 PBKDF2。

Node.js' 加密模块提供了createHash(algorithm)功能。您可以在其中直接指定 SHA-256。 PBKDF2 是一种仅在底层使用不同哈希函数的算法。

如果您想要散列密码,那么使用具有大量迭代(> 86,000)的 PBKDF2 和与密码散列一起存储的随机盐会更安全。

Java 在其标准库中支持 PBKDF2。

如果你真的想直接使用 SHA-256 而我强烈反对,你可以使用以下代码:

var crypto = require('crypto');
var key = "123";
var salt = "test@gmail.com";

key = crypto.createHash('sha256')
        .update(key, "utf8")
        .update(makeHash(salt))
        .digest("base64");

console.log(key);

function makeHash(val) {
    return crypto.createHash('sha256').update(val, "utf8").digest();
}

输出:

/pyQf3JCj5XoczfsYJ4LUb+y0DONGMl/AFzLiBTo8LA=

请注意 Hash.digest() 采用可选的输出编码而不是附加数据。