重新散列哈希 (SHA512)

本文关键字:SHA512 哈希 新散列 | 更新日期: 2023-09-27 18:37:18

我们正在遵循一个非常标准的用户ID/密码检查。我们将散列密码存储在数据库中。当用户输入凭据时,我们会对输入的密码进行哈希处理,然后与数据库的密码进行比较。如果它们匹配,则用户将进行身份验证。

现在,负载测试下的登录过程正在大大减慢,因此要求我查看它。VS 2013 Profiler指出哈希方法是一种热路径。看看有问题的方法,我们正在循环哈希过程??

private const int totalHashCount = 1723;
public string CreateHash(string salt, string password, int securityIndex)
{
  string hashedPass = this.GenerateHashString(salt + password, securityIndex);
  for (int i = 1; i <= totalHashCount; i++)
  {
    hashedPass = this.GenerateHashString(hashedPass, securityIndex);
  }
  return hashedPass;
}

我去找了开发人员,他说客户的安全团队希望我们重新散列哈希值,并做一些大于1000的质数......他提供了电子邮件作为文档。

现在我不是密码学专家,我们与客户的关系很好,所以在我去找他们并将这个重新哈希循环与他们的性能问题联系起来之前,我想看看像这样的重新哈希是否真的增加了安全性?

据我了解,单个哈希实际上是不可能反转的,那么为什么要浪费循环来重复这个过程呢?

思潮?


编辑

添加了生成哈希:

protected internal string GenerateHashString(string textToHash, int securityIndex = 0)
{
   UnicodeEncoding uEncode = new UnicodeEncoding();
   SHA512Managed sha = new SHA512Managed();
   byte[] bytVal = uEncode.GetBytes(textToHash + hashIntPool[securityIndex].ToString());
   byte[] hashVal = sha.ComputeHash(bytVal);
   return Convert.ToBase64String(hashVal);
 }

重新散列哈希 (SHA512)

重复哈希操作对于保护密码身份验证至关重要,但您做错了,因此确实浪费了 CPU 而一事无成。

您应该使用像 PBKDF2 这样的算法,该算法在每一轮哈希中都包含密码,以保留密码的所有不可预测性。 bcrypt,尤其是scrypt也是不错的选择。

此外,一千轮还远远不够;为了防止离线字典攻击,您需要哈希操作相对较慢,即使在攻击者的专用密码测试硬件上执行也是如此。选择质数回合是毫无意义的笨拙。回合数将取决于您选择的算法,但对于带有 SHA-256 的 PBKDF2,10,000 到 100,000 发应该提供合理的安全级别。

需要缓慢的算法来防止获取哈希的攻击者快速尝试许多不同的密码以查看哪个密码产生相同的哈希。确实,安全哈希不可反转,但它不会停止猜测,攻击者善于优先考虑他们的猜测,以首先尝试最有可能的密码。哈希的重复提供了这种必要的缓慢。

这在StackOverflow上已经讨论过很多次了。我向您推荐以前的答案以获取更多背景信息。

在 C# 中,可以使用 Rfc2898DeriveBytes 安全地执行密码哈希。您可以将 Base-64 中的派生密钥编码为字符串存储,或者实际将其用作加密密钥来加密已知的纯文本,就像 bcrypt 算法所做的那样。你会注意到Rfc2898DeriveBytes使用了"盐",我在其他地方讨论过;需要将此值与哈希值一起存储,以便稍后执行身份验证。

重复哈希的"拉伸"技术用于使暴力攻击更加困难。 如果散列密码需要 0.1 秒(由于重复),那么攻击者最多每秒可以尝试 10 个密码来找到匹配项。 如果您加快哈希过程,使其需要一微秒,那么攻击者每秒可以测试一百万个密码。

您需要在速度与安全性之间取得平衡。 用户登录只需要足够快以满足用户,因此 0.1 到 0.5 秒可能是可以接受的。

如果您的服务器过载,请购买更快的处理器,或购买专用的哈希服务器。 这将比数据泄露的法律后果便宜得多。