完整性检查:盐和哈希密码

And*_*ans 5 c# hash salt password-protection

我对哈希密码和盐值有所了解.因为我对哈希和加密很新,我想我会把它发给你.为每个用户帐户生成唯一的盐是否更安全,然后在数据库中存储salt和散列值?或者,保持一个盐值安全存储并重新使用每次我输入密码?

例如,用户将使用密码:

"secret"
Run Code Online (Sandbox Code Playgroud)

我的代码会生成一个salt值:

"d1d0e3d4b3d1ed1598a4e77bb614750a2a175e"
Run Code Online (Sandbox Code Playgroud)

然后哈希结果得到:

"e8187dcbe8e2eabd4675f3a345fe21c98affb
 5544a9278461535cb67265b6fe09a11dbef572
 ce3a4a8f2275839927625cf0bc7bc46fc45d51
 12d7c0713bb4a3"
Run Code Online (Sandbox Code Playgroud)

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

有什么想法吗?就像我说的,这是对我的想法的理智检查.

Luk*_*keH 7

在我看来,每个用户存储一个独特的盐是个好主意.每次用户登录时重新生成salt/hash组合都是没有意义的,除非你有CPU周期要刻录.我建议使用像Rfc2898DeriveBytes类这样的东西来生成一个安全的salt/hash组合:

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

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);
}
Run Code Online (Sandbox Code Playgroud)

并相应检查密码:

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");
}
Run Code Online (Sandbox Code Playgroud)


Tho*_*rin 5

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

您可能需要研究使用BCrypt.NET(经过验证的密码哈希算法的.NET实现),而不是自己动手做。

用法很简单:

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

// Upon login
bool validPassword = BCrypt.CheckPassword(password, hashedPassword);
Run Code Online (Sandbox Code Playgroud)

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

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