我创建了一个简单的MVC4应用程序并注册了一个用户.usrname和密码存储在名为AspNetUsers的表中.该表没有盐场.
我理解的方式是当用户登录时; 他们输入用户名和密码.然后将盐与输入的密码连接起来,并与数据库中的密码进行比较.这不正确吗?即
Hash(PasswordEntered) + Salt = Password in database = authenticated
Hash(PasswordEntered) + Salt <> Password in database = not authenticated
Run Code Online (Sandbox Code Playgroud)
有一个名为:aspnetusers.SecurityStamp的字段,但我的研究告诉我,这不是Salt.
更新
我刚读过Scott Chamberlain.请参阅以下步骤:
1)用户在注册期间输入:Hello123作为密码,Salt(随机生成)为:456,然后输入PasswordHash的密码为:Hello123 + 456 2)然后用户尝试登录并输入Hello123(正确)作为密码.盐(随机生成)为:567.因此Hello123 + 456与Hello123 + 567进行比较,验证失败.
在这种情况下,用户输入正确的密码并且未经过身份验证.我显然缺少一些基本的东西.
您的模式不正确,正确的模式是
Hash(PasswordEntered + Salt) = hash in database = authenticated
Hash(PasswordEntered + Salt) <> hash in database = not authenticated
Run Code Online (Sandbox Code Playgroud)
ASP.net提供程序的工作方式是将其存储Salt + Hash(PasswordEntered + Salt)在密码字段中。因此,当您测试密码时,只需在盐中使用分隔符之前的部分,然后将其与分隔符之后的部分进行比较。
在更新中,您出错的部分是用户登录时没有随机生成的盐。它重新使用了用户注册时随机生成的盐,该盐以纯文本格式存储在数据库中,并且没有散列。
与 asp.net core 3 相同。
Salt + Hash连接并存储到passwordHash数据库中的字段中。
这是如何生成passwordHash 的源代码。
*password参数为明文密码。
*subkey是个hash。
https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Extensions.Core/src/PasswordHasher.cs
private static byte[] HashPasswordV3(string password, RandomNumberGenerator rng, KeyDerivationPrf prf, int iterCount, int saltSize, int numBytesRequested)
{
// Produce a version 3 (see comment above) text hash.
byte[] salt = new byte[saltSize];
rng.GetBytes(salt);
byte[] subkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, numBytesRequested);
var outputBytes = new byte[13 + salt.Length + subkey.Length];
outputBytes[0] = 0x01; // format marker
WriteNetworkByteOrder(outputBytes, 1, (uint)prf);
WriteNetworkByteOrder(outputBytes, 5, (uint)iterCount);
WriteNetworkByteOrder(outputBytes, 9, (uint)saltSize);
Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length);
Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length);
return outputBytes;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2192 次 |
| 最近记录: |