散列密码验证不起作用

Verification of Hashing password is not working

我问了一个问题,得到了很多很好的反馈和很好的回答。我假设我对 2 个哈希值的验证检查有问题。也许循环中的代码很好,但是我理解字节和 base64 等的代码是问题吗?

这是原题。

问题是这些哈希值不匹配 if (resultHash.Equals(hashPassword))

代码

public string BuildVerify()
{

    string password = "";
    string salt = "";
    byte[] result;


    using (var sha256 = SHA256.Create())
    {
        password = "hovercraft";

        // step 1: you can use RNGCryptoServiceProvider for something worth using
        var passwordHashing = new PasswordHashing();
        salt = passwordHashing.CreateRandomSalt();

        // step 2
        string hash =
           Convert.ToBase64String(sha256.ComputeHash(Encoding.UTF8.GetBytes(salt + password)));

        // step 3
        result = sha256.ComputeHash(Encoding.UTF8.GetBytes(salt + hash));

        // step 4
        for (int i = 0; i < 60000; i++)
        {
            result =
             sha256.ComputeHash(Encoding.UTF8.GetBytes(salt + Convert.ToBase64String(result)));
        }
    }


    // TESTING  VERIFY this works ..

    string SaltAndPwd = string.Concat(password, salt);
    SHA256 sha2 = SHA256Managed.Create();
    byte[] buff = sha2.ComputeHash(Encoding.Unicode.GetBytes(SaltAndPwd));
    string resultHash = Convert.ToBase64String(buff);
    string hashPassword = Convert.ToBase64String(result);

    if (resultHash.Equals(hashPassword))
    {
        // perfect 
    }





    return "";

}


public class PasswordHashing
{

     public string CreateRandomSalt()
     {
        string password = "";
        password = HashPassword.CreateSalt(8) + "=";
        password = password.Replace("/", "c");
        return password;
     }

  }

public static string CreateSalt(int size)
{
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

    byte[] buff = new byte[size];
    rng.GetBytes(buff);
    return Convert.ToBase64String(buff);
}

更新 - 问题

好的,我正在使用答案中的代码,但显然我的假设不正确,因为我无法使用我的代码来验证

            // This should be stored in your DB for example along with the hash result
            var newsalt = SOPasswordHasher.GetSalt();

            // We calculate the hash then store the result. Next time you want to authenticate someone
            // You'll have to reuse the same salt and recalculate the hash then compare 
            // the stored hash with the new one
            var result = Convert.ToBase64String(SOPasswordHasher.Hash("hovercraft", newsalt));

            string SaltAndPwd = string.Concat("hovercraft", newsalt);
            SHA256 sha2 = SHA256Managed.Create();
            byte[] buff = sha2.ComputeHash(Encoding.Unicode.GetBytes(SaltAndPwd));
            string resultHash = Convert.ToBase64String(buff);

            if (result.Equals(resultHash))
            {
                // perfect 
            }

这是您可以使用的可重用 class(较少依赖转换为 base64):

class SOPasswordHasher
{
    /// <summary>
    /// Password Hasher
    /// </summary>
    /// <param name="password">The password you want to hash</param>
    /// <param name="salt">byte array of (crypto-secure) random values</param>
    /// <param name="iterations">Number of iterations. default is 60,000</param>
    /// <returns>Byte array containing the hashed password</returns>

    public static byte[] Hash(string password, byte[] salt, int iterations = 60000)
    {
        using (var sha256 = SHA256.Create())
        {
            byte[] passwordBytes = Encoding.UTF8.GetBytes(password);

            // step 2
            byte[] hash = sha256.ComputeHash(passwordBytes.Concat(salt).ToArray());

            // step 3
            byte[] result = sha256.ComputeHash(salt.Concat(hash).ToArray());

            // step 4
            for (int i = 0; i < iterations; i++)
            {
                result =
                    sha256.ComputeHash(salt.Concat(result).ToArray());
            }

            return result;
        }
    }

    public static byte[] GetSalt(int size = 32)
    {
        byte[] salt = new byte[size];
        using (var cryptoServiceProvider = new RNGCryptoServiceProvider())
        {
            cryptoServiceProvider.GetBytes(salt);
        }
        return salt;
    }
}

这是一个用法示例:

// This should be stored in your DB for example along with the hash result
var salt = SOPasswordHasher.GetSalt();

// We calculate the hash then store the result. Next time you want to authenticate someone
// You'll have to reuse the same salt and recalculate the hash then compare 
// the stored hash with the new one
var result = Convert.ToBase64String(SOPasswordHasher.Hash("hovercraft", salt));

重要提示:我不保证此代码可以安全使用,因为我不是安全专家。 Bruce Schneier 说得最好:"Amateurs Produce Amateur Cryptography"