【问题标题】:Password Hashing - Why salt 60,000 times密码哈希 - 为什么要加盐 60,000 次
【发布时间】:2016-09-17 11:13:46
【问题描述】:

我在一家财富 100 强的公司工作,我正忙于从 SHA1 迁移到 SHA-2 的安全任务。这不是我的专业领域,但当我学习密码学时,我正在质疑过时的信息等......

  1. 显然需要 SHA-2 而不是 SHA-1,但是当安全团队知道密码 + salt 的散列正在使用 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));
}

如何使这种散列法正常工作?

更新发现PPT幻灯片

使用代码更新 - 哈希验证的实施问题

问题是当我对正在尝试的代码使用检查时 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);
    }

新问题 认为我会继续创建一个新问题,提前感谢大家。 Verification of Hashing password is not working

【问题讨论】:

  • 循环没有意义。这基本上是在浪费 CPU 时间,因为每次迭代的结果都是相同的。此外,每个密码的盐必须是唯一的才能生效。
  • 你能给我举个例子吗?
  • @Nasreddine 即使不一样,它仍然没用,因为盐是公开可读的。
  • 是的,关键是你应该每次都取结果哈希+盐和重新哈希。这个想法是,这样做可以否定彩虹表,并减慢检查匹配密码的过程。
  • @MillRunner 我建议询问该幻灯片的作者。要么他们用一种奇怪的方式措辞(他们的意思是别的),要么他们真的不知道加盐是如何工作的。无论哪种方式,我都会要求澄清。

标签: c# hash sha256 sha


【解决方案1】:

我不明白为什么我没有被告知使用 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)));
    }
}

【讨论】:

  • 幻灯片所暗示的内容。
  • 好吧,我无法像往常一样正确验证/验证。我可能需要创建一个新问题,但我首先会在问题等中发布我上面的代码。
  • 新问题基于你和我的代码stackoverflow.com/questions/37354199/…
  • @MillRunner 我正在尝试写一个完整的答案。
  • @Nasreddine -- 非常感谢,我发布的问题得到了很多反馈(新问题)我确定你的代码很好......我不够聪明,无法编写验证/验证它的正确代码。提前非常感谢
【解决方案2】:

在我看来,这看起来像是尝试重新实现 PBKDF2 算法,以获得成本因素。

通常不建议对安全功能进行实验,而应使用经过验证的、经过良好测试的算法。您对上述算法的担忧是有道理的,请尝试说服您的团队改用 BCrypt.Net 或 PBKDF2。

当您选择 PBKDF2 时,您可以使用内置的 dotnet 类 Rfc2898DeriveBytes 来计算带有 HMACSHA1(即使在今天也是标准)的 PBKDF2,或者您可以使用支持其他哈希函数的实现,例如 @ 987654324@.

【讨论】:

  • 我同意,但在我所在的公司,遗憾的是他们不想要 PBKDF2 或 BCrypt - 这是一场我无法赢得的战斗......我现在知道,只要我被允许我会实施更好的。
  • 我在使用该代码时遇到问题并验证 .. :/ ( OP )
猜你喜欢
  • 2012-01-08
  • 2011-12-06
  • 2015-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-25
  • 2013-09-11
  • 2010-11-30
相关资源
最近更新 更多