5

我对散列密码和盐值有一个想法。由于我对散列和加密比较陌生,所以我想我会把这个发布给你。为每个用户帐户生成唯一的盐,然后将盐和散列值存储在数据库中会更安全吗?或者,每次我对密码进行哈希处理时,安全地存储一个盐值并重新使用它?

例如,用户将使用密码:

"secret"

我的代码将生成一个盐值:

"d1d0e3d4b3d1ed1598a4e77bb614750a2a175e"

然后哈希结果得到:

"e8187dcbe8e2eabd4675f3a345fe21c98affb
 5544a9278461535cb67265b6fe09a11dbef572
 ce3a4a8f2275839927625cf0bc7bc46fc45d51
 12d7c0713bb4a3"

创建帐户时,哈希结果和盐将存储在用户配置文件中的数据库中。然后,每次用户登录时,都会生成一个新的 salt,密码和 salt 会重新散列并存储在数据库中。

有什么想法吗?就像我说的,这是对我的想法的健全性检查。

4

4 回答 4

7

在我看来,为每个用户存储一个独特的盐是一个好主意。每次用户登录时重新生成盐/哈希组合有点毫无意义,除非你有 CPU 周期要烧掉。我建议使用类之Rfc2898DeriveBytes类的东西来生成安全的盐/哈希组合:

从密码生成哈希的简单示例:

string password = GetPasswordFromInput();

using (var deriveBytes = new Rfc2898DeriveBytes(password, 32))  // 32-byte salt
{
    byte[] salt = deriveBytes.Salt;
    byte[] hash = deriveBytes.GetBytes(32);  // 32-byte hash
    SaveToDatabase(salt, hash);
}

以及相应的密码检查:

string password = GetPasswordFromInput();
byte[] salt = GetSaltFromDatabase();
byte[] hash = GetHashFromDatabase();

using (var deriveBytes = new Rfc2898DeriveBytes(password, salt))
{
    if (deriveBytes.GetBytes(32).SequenceEqual(hash))
        Console.WriteLine("Password matches");
    else
        throw new Exception("Bad password");
}
于 2010-07-28T15:46:15.140 回答
5

正如 Adam 已经提到的,每次用户登录时散列和存储密码并没有真正的目的。

与其自己动手,不如考虑使用BCrypt.NET,这是一种经过验证的密码散列算法的 .NET 实现。

用法很简单:

// When setting password
string hashedPassword = BCrypt.HashPassword(password, BCrypt.GenerateSalt());

// Upon login
bool validPassword = BCrypt.CheckPassword(password, hashedPassword);

如果您愿意,它允许您改变计算密码哈希的计算成本,从而使某人更难对他们可能已经获得的数据库进行字典攻击。这是通过向GenerateSalt方法调用添加参数来完成的。

BCrypt 算法的详细信息可以在这里找到

于 2010-07-28T15:25:16.020 回答
3
  • 每个用户都应该有自己独特的盐。
  • 每次用户登录时都没有必要更新 salt,这在安全性方面没有真正的用途。
  • 盐应该是随机生成的,并且不以任何方式链接到密码。

盐的目的是防止预计算攻击(例如彩虹表)。因此,如果两个用户具有相同的密码,他们将不会拥有相同的最终哈希值。如果盐是系统范围的而不是每个用户的,那么情况就不会如此,攻击者只需要预先计算一次系统的所有密码。如果每个用户都有自己的 salt,则需要对每个用户单独进行预计算攻击,从而使攻击不可行。

使用加盐哈希并不能防止暴力字典攻击。您将需要使用其他方法来防止这些。

于 2010-07-28T15:49:12.527 回答
1

盐的真正目的是防止预计算攻击,因为盐本身不应该是秘密的(即可以从外部世界访问它)。因此,它不旨在提供针对暴力破解的安全性,因为它(几乎)与哈希(密码)一样容易散列(Salt+Password)。

如果您认为有人实际上会为您的单个盐构建一个预先计算的表到密码数据库,然后使用该表查找他们在您的数据库中找到的加盐密码哈希,那么您应该为每个密码使用唯一的盐。否则,不要担心。

于 2010-07-28T15:32:26.387 回答