健全性检查:盐和散列密码

发布于 2024-09-11 18:40:33 字数 560 浏览 4 评论 0原文

我对哈希密码和盐值有一个想法。由于我对哈希和加密相当陌生,所以我想我会将其发布给您。为每个用户帐户生成唯一的盐,然后将盐和哈希值存储在数据库中会更安全吗?或者,安全地存储单个盐值并在每次对密码进行哈希处理时重复使用该盐值?

例如, 用户将使用密码:

"secret"

我的代码将生成盐值:

"d1d0e3d4b3d1ed1598a4e77bb614750a2a175e"

然后对结果进行哈希处理以获得:

"e8187dcbe8e2eabd4675f3a345fe21c98affb
 5544a9278461535cb67265b6fe09a11dbef572
 ce3a4a8f2275839927625cf0bc7bc46fc45d51
 12d7c0713bb4a3"

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

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

I had an idea about hashed passwords and salt values. Since I'm rather new to hashing and encryption, I thought I'd post this to you. Would it be more secure to generate a unique salt for each user account, then store the salt and hashed values in the database? Or, keep a single salt value securely stored and re-use that each time I hashed a password?

For example,
A user would use the password:

"secret"

My code would generate a salt value of:

"d1d0e3d4b3d1ed1598a4e77bb614750a2a175e"

Then hash the result to get:

"e8187dcbe8e2eabd4675f3a345fe21c98affb
 5544a9278461535cb67265b6fe09a11dbef572
 ce3a4a8f2275839927625cf0bc7bc46fc45d51
 12d7c0713bb4a3"

The hashed result and salt would then be stored in the database in the users profile when their account was created. Then, each time the user logged on, a new salt would be generated, the password and salt rehashed and stored in the database.

Any thoughts? Like I said, this is a sanity check on an idea I had.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

时光清浅 2024-09-18 18:40:33

在我看来,为每个用户存储一个独特的盐是一个好主意。每次用户登录时重新生成 salt/hash 组合有点毫无意义,除非您有 CPU 周期需要消耗。我建议使用类似 Rfc2898DeriveBytes< /code>类来生成安全的盐/哈希组合:

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

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");
}

Storing a unique salt per user is a good idea in my opinion. Re-generating the salt/hash combination every time the user logs in is a bit pointless unless you've got CPU cycles to burn. I'd recommend using something like the Rfc2898DeriveBytes class to generate a secure salt/hash combo:

Simple example of generating a hash from a password:

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);
}

And the corresponding checking of a password:

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");
}
安人多梦 2024-09-18 18:40:33

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

您可能不想自己动手,而是考虑使用 BCrypt.NET,经过验证的密码哈希算法的 .NET 实现。

用法非常简单:

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

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

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

BCrypt 算法的详细信息可以在此处找到

As Adam already mentioned, hashing and storing the password each time a user logs in serves no real purpose.

Rather than rolling your own, you might want to look into using BCrypt.NET, a .NET implementation of a proven password hashing algorithm.

Usage is very simple:

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

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

It allows you to vary the computational costs of calculating a password hash if you want to, making it more difficult for someone to do a dictionary attack on a database they might have obtained for example. This is done by adding a parameter to the GenerateSalt method call.

The details of the BCrypt algorithm can be found here.

森林很绿却致人迷途 2024-09-18 18:40:33
  • 每个用户都应该有自己独特的盐。
  • 每次用户登录时都没有必要更新盐,这对于安全性没有真正的作用。
  • 盐应该是随机生成的,并且不以任何方式链接到密码。

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

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

  • Each user should have their own unique salt.
  • There's no point updating the salt each time a user logs in, this serves no real purpose with regards to security.
  • The salt should be randomly generated and not linked to the password in any way.

The purpose of a salt is to protect against pre-computation attacks (such as rainbow tables). So if two users have the same password, they won't have the same final hash. If the salt is system wide and not per user, then this wouldn't be the case and an attacker only need to pre-compute all of the passwords for your system once. If each user has their own salt, then a pre-computation attack would need to be done on each user individually, making the attack infeasible.

Using a salted hash does not protect against brute force dictionary attacks. You would need to use other methods to protect against those.

风蛊 2024-09-18 18:40:33

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

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

The real purpose of a salt is to prevent against precomputation attacks, as the salt itself is NOT supposed to be secret (i.e. it is fine to have it accessible from the outside world). It is therefore not intended to provide security against brute forcing since it's (almost) as easy to hash(Salt+Password) as it is hash(Password).

If you believe someone will actually build a precomputed table of your one single salt to a database of passwords, then look up the salted password hashes they found in your database with said table, then you should use a unique salt for each password. Otherwise, don't worry about it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文