【发布时间】:2020-03-12 02:03:42
【问题描述】:
我正在尝试使用来自Microsoft Docs Hashing 的代码来散列密码并将其存储在数据库中。保存哈希和盐工作正常。 我的哈希方法:
public Tuple<string,string> PasswordCrypting(string password)
{
byte[] salt = new byte[128 / 8];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(salt);
}
string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt:salt,
prf: KeyDerivationPrf.HMACSHA1,
iterationCount: 10000,
numBytesRequested: 256 / 8));
Tuple<string, string> credentials = new Tuple<string, string>(hashed, Convert.ToBase64String(salt));
return credentials;
}
在用户登录时,我从数据库中检索 salt,并使用它使用用户的密码输入和 salt 重新创建散列。我会使用我得到的哈希值与存储在数据库中的哈希值进行比较。
public string PasswordDecrypting(string username,string password)
{
string salt = _userManager.GetPassSalt(username);
string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: Convert.FromBase64String(salt),
prf: KeyDerivationPrf.HMACSHA1,
iterationCount: 10000,
numBytesRequested: 256 / 8));
return hashed;
}
问题是我永远无法获得与数据库中相同的哈希值。我调试了我的代码,盐与数据库中的盐匹配,密码字符串与第一次散列时相同;使用了相同的算法,但生成的哈希与我应该得到的不同。
这个算法是不是让它永远不会产生相同的散列,如果是这样,我该如何重新创建我的散列?
【问题讨论】:
-
盐与数据库中的盐相匹配,但您确定它与用于创建初始哈希的盐相同吗?
-
有了哈希,就没有“解密”。相反,您通过用于原始的 same 散列函数运行输入。拥有一个单独的“Decyrpt”功能是没有意义的。
-
PasswordCrypting 应该将 Salt(由外部代码为其生成)作为参数。那么它是否从随机生成或数据库中获取盐并不重要。你可以把它变成一个简单的字符串返回值。
-
@JonathonChase 如何确保保存用于创建哈希的那个?
-
确保保存用于创建哈希的 [salt] 的方式是确保保存用于创建哈希的盐。您可以将其作为用户记录的一部分保存在数据库中,或者以不会针对特定用户更改的方式进行计算。例如,如果您有一个与用户记录关联的不变 GUID,请将其用作盐。
标签: c# asp.net-core hash passwords