C# 使用Pbkdf2加密使用Salt加密和验证哈希密码
我正在使用以下代码创建哈希密码和salt:C# 使用Pbkdf2加密使用Salt加密和验证哈希密码,c#,encoding,asp.net-core,cryptography,passwords,C#,Encoding,Asp.net Core,Cryptography,Passwords,我正在使用以下代码创建哈希密码和salt: // generate a 128-bit salt using a secure PRNG byte[] salt = new byte[128 / 8]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(salt); } // derive a 256-bit subkey (use HMACSHA1 with 10,000 iterations) strin
// generate a 128-bit salt using a secure PRNG
byte[] salt = new byte[128 / 8];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(salt);
}
// derive a 256-bit subkey (use HMACSHA1 with 10,000 iterations)
string hashedPassword = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: salt,
prf: KeyDerivationPrf.HMACSHA1,
iterationCount: 10000,
numBytesRequested: 256 / 8));
我正在数据库中存储HashedPassword和Salt
现在我想验证用户登录时的密码:
public bool VerifyPassword(string userEnteredPassword, string dbPasswordHash, string dbPasswordSalt)
{
string hashedPassword = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: userEnteredPassword,
salt: Encoding.ASCII.GetBytes(dbPasswordSalt),
prf: KeyDerivationPrf.HMACSHA1,
iterationCount: 10000,
numBytesRequested: 256 / 8));
return dbPasswordHash == hashedPassword;
}
这不起作用,我得到的哈希密码与数据库中存储的密码完全不同。据我所知,您应该在用户登录时输入的密码前加上salt,然后运行相同的Hash password函数。难道上述情况不等同于此吗?正如马丁·博德维斯所提到的,ASCII是问题所在。下面的代码返回true。我所做的所有更改都是
salt:Encoding.ASCII.GetBytes(dbPasswordSalt),
到salt:System.Convert.FromBase64String(dbPasswordSalt),
正如Maarten Bodewes提到的,ASCII是问题所在。下面的代码返回true。我所做的所有更改都是
salt:Encoding.ASCII.GetBytes(dbPasswordSalt),
到salt:System.Convert.FromBase64String(dbPasswordSalt),
byte[] salt = new byte[128 / 8];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(salt);
}
return Convert.ToBase64String(salt);
然后使用该salt创建哈希密码
string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: salt,
prf: KeyDerivationPrf.HMACSHA1,
iterationCount: 10000,
numBytesRequested: 256 / 8));
保存在某处使用的盐(例如:数据库)
保存该用户的哈希密码
- 检索该用户的salt和哈希密码李>
- 使用检索到的salt和用户输入的密码创建哈希密码李>
- 检查新哈希密码和存储的密码是否相同
byte[] salt = new byte[128 / 8];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(salt);
}
return Convert.ToBase64String(salt);
然后使用该salt创建哈希密码
string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: salt,
prf: KeyDerivationPrf.HMACSHA1,
iterationCount: 10000,
numBytesRequested: 256 / 8));
保存在某处使用的盐(例如:数据库)
保存该用户的哈希密码
- 检索该用户的salt和哈希密码李>
- 使用检索到的salt和用户输入的密码创建哈希密码李>
- 检查新哈希密码和存储的密码是否相同
看起来不错;我会确保你的盐分在两种食物之间是一样的two@BradleyDotNET我在想字节[]到字符串和字符串到字节[]的转换可能发生了一些问题。您的salt是一个随机缓冲区,而不是字符串,因此
string dbPasswordSalt
不是您想要的。将其作为varbinary存储在数据库中,并将其读回字节[]
以供salt:
使用。如果使用varbinary,则不需要base64往返,并且存储大小更小。这两个因素都不太重要,所以取决于您。一个小建议:使用UTF-8作为密码和其他要散列的参数。它们在Android、BSDs、Unix、Linux、iOS、OSX和Windows上是一致的。东西:只要工作“.ASCII、UTF-16和UTF-32将使您在某些时候在某些平台上执行转换。它看起来是正确的;我将确保您的盐在不同的平台之间实际上是相同的two@BradleyDotNET我在想,字节[]到字符串和字符串到字节[]可能发生了什么事情转换。您的salt是一个随机缓冲区,不是字符串,因此string dbPasswordSalt
不是您想要的。将其作为varbinary存储在数据库中,并将其读回字节[]
对于salt:
如果你使用varbinary,你不需要base64往返,而且存储空间也更小。这两个因素都不太重要,所以取决于你。一个小建议:使用UTF-8作为密码和其他要散列的参数。它们在Android、BSDs、Unix、Linux、iOS、OS X和Windows上是一致的。注意事项:j“工作”。ASCII、UTF-16和UTF-32将使您有时在某些平台上执行转换。