哈希相同的字符串和相同的盐给出不同的哈希结果

Hashing same string and same salt giving different hash result

我正在尝试使用 Microsoft Docs Hashing 中的代码来散列密码并将其存储在数据库中。保存哈希和盐可以正常工作。 我的哈希方法:

public Tuple<string,string> PasswordCrypting(string password)
    {
        byte[] salt = new byte[128 / 8];
        using (var rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(salt);
        }
        string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
        password: password,
        salt:salt,
        prf: KeyDerivationPrf.HMACSHA1,
        iterationCount: 10000,
        numBytesRequested: 256 / 8));
        Tuple<string, string> credentials = new Tuple<string, string>(hashed, Convert.ToBase64String(salt));
        return credentials;
    }

在用户登录时,我从数据库中检索盐,并使用它使用用户输入的密码和盐重新创建散列。我会使用我得到的哈希值与存储在数据库中的哈希值进行比较。

public string PasswordDecrypting(string username,string password)
    {
        string salt = _userManager.GetPassSalt(username);
        string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
        password: password,
        salt: Convert.FromBase64String(salt),
        prf: KeyDerivationPrf.HMACSHA1,
        iterationCount: 10000,
        numBytesRequested: 256 / 8));
        return hashed;
    }

问题是我永远无法获得与数据库中相同的哈希值。我调试了我的代码,salt 与数据库中的匹配,密码字符串与第一次散列时相同;使用相同的算法,但生成的哈希值与我应该得到的不同。

这个算法是这样设计的,所以它永远不会生成相同的哈希值,如果是这样,我该如何重新创建我的哈希值?

我已经创建了一个单元测试来测试您的代码。并且必须得出您没有正确存储盐的结论,或者您在存储之前或从数据库中检索盐之后以某种方式更改了盐。

我写了下面的单元测试:

    [TestMethod]
    public void Test_SaltGeneration()
    {
        var password = "48F3A112-F574-4B25-B226-CE97888FCBCB";

        var firstResult = PasswordCrypting(password);

        var secondResult = PasswordDecrypting(password, firstResult.salt);

        Assert.IsTrue(firstResult.hash.Equals(secondResult));
    }

    public (string hash, string salt) PasswordCrypting(string password)
    {
        byte[] salt = new byte[128 / 8];
        using (var rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(salt);
        }
        string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
            password: password,
            salt: salt,
            prf: KeyDerivationPrf.HMACSHA1,
            iterationCount: 10000,
            numBytesRequested: 256 / 8));

        return (hashed, Convert.ToBase64String(salt));
    }

    public string PasswordDecrypting(string password, string salt )
    {
        string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
            password: password,
            salt: Convert.FromBase64String(salt),
            prf: KeyDerivationPrf.HMACSHA1,
            iterationCount: 10000,
            numBytesRequested: 256 / 8));
        return hashed;
    }

如您所料。这个测试通过。暗示我的第一个断言。