密码哈希 - 为什么要加盐6万次

5
我在一家财富100强公司工作,被指派负责将安全性从SHA1转移到SHA-2。这不是我的专业领域,但是随着我学习密码学,我开始对过时的信息产生疑问等等...
  1. 明显需要使用SHA-2而非SHA-1,但当安全团队知道密码+盐值的哈希使用了SHA算法,并且GPU可以快速破解数十亿个哈希时,我不明白为什么他们没有告诉我使用bcrypt或其他慢速哈希等效方法来保护密码,为什么?
  2. 我被告知要创建60,000次盐值,但我在互联网上搜索并没有看到任何建议或示例,为什么?
我正在使用C#。
string SaltAndPwd = string.Concat(plainTextPassword, salt);
SHA256 sha2 = SHA256Managed.Create();
byte[] buff = sha2.ComputeHash(Encoding.Unicode.GetBytes(SaltAndPwd));

我想我不是被告知要一遍又一遍地创建盐,而是要一遍又一遍地创建哈希值。

这个逻辑是否合适?

string plainTextPassword = "aF7Cvs+QzZKM=4!";  
string salt = "o9kc5FvhWQU==";
SHA256 sha2 = SHA256Managed.Create();

for(var i = 0; i <= 60000; i++)
{
   byte[] buff = sha2.ComputeHash(Encoding.Unicode.GetBytes(SaltAndPwd));
}

我该如何使哈希正常工作?
更新:找到了 PowerPoint 幻灯片。

enter image description here

使用代码进行更新 - 实现哈希验证时出现问题

问题在于当我使用代码检查时,尝试使用以下代码:

if (resultHash.Equals(hassPassword))

但它不匹配...

    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 hassPassword = Convert.ToBase64String(result);

        if (resultHash.Equals(hassPassword))
        {
            // 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);
    }

新问题 我想提出一个新的问题,谢谢大家提前帮助。 验证哈希密码不起作用


4
循环没有意义。由于每次迭代的结果相同,它基本上是在浪费CPU时间。另外,为了让盐起作用,每个密码的盐必须是唯一的。 - Nasreddine
即使不是同一个,由于盐值是公开可读的,所以仍然没有用。 - Rob
6
每次都需要将生成的哈希值与盐混合重新进行哈希,这是关键。这样做的想法是为了抵消彩虹表攻击,并减慢匹配密码的检查过程。 - gview
@Nasreddine 我知道。我的观点是,浪费时间去创建盐是无用的,因为攻击者可以立即访问它。 - Rob
请查看此线程 https://dev59.com/onRC5IYBdhLWcg3wSu97 - tolanj
显示剩余11条评论
2个回答

9

我不明白为什么在密码方面我没有被告知要使用bcrypt或其他缓慢的等效方法

我猜这就是为什么他们要求您进行60000次哈希的原因。增加工作因素并减慢暴力攻击。

如何使此哈希正常工作?

像这样:

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

    // step 1: you can use RNGCryptoServiceProvider for something worth using
    string salt = GenerateSalt();

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

    // step 3
    byte[] 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)));
    }
}

这是幻灯片所提示的内容。 - Jodrell
嗯,我在验证/验证这个问题上遇到了麻烦,就像我通常做的那样。我可能需要创建一个新的问题,但首先我会在问题中发布我的代码等。 - user5299399
基于你的代码和我的代码,有一个新的问题。http://stackoverflow.com/questions/37354199/verification-of-hashing-password-is-not-working-complete-code-shown - user5299399
@MillRunner 我正在努力撰写完整的答案。 - Nasreddine
@Nasreddine -- 非常感谢,我发布的问题得到了很多反馈(新问题),我相信你的代码是没问题的...但我不够聪明去编写适当的代码来验证/验证它。非常感谢您的提前帮助。 - user5299399

4
对我来说,这似乎是尝试重新实现PBKDF2算法以获得成本因素。
通常不建议对安全功能进行实验,而应使用经过验证的经过充分测试的算法。您对上述算法的担忧是合理的,请尝试说服您的团队切换到BCrypt.Net或PBKDF2。
当您选择PBKDF2时,您可以使用内置的dotnet类Rfc2898DeriveBytes计算带有HMACSHA1的PBKDF2(即使今天也是标准),或者您可以使用支持其他哈希函数的实现,例如PBKDF2 with SHA-256

我同意,但是在我所在的公司,遗憾的是他们不想要PBKDF2或BCrypt - 这是我无法赢得的战斗... 我现在知道,只要有机会,我就会实现更好的方法。 - user5299399
我对那段代码有问题并且需要验证... :/ (OP) - user5299399

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接