我看到了关于密码哈希和盐的多个问题,但它们似乎都对我失败了。我使用此函数对其进行哈希/加盐,然后将其放入数据库:
public string HashPassword(string password)
{
byte[] salt;
new RNGCryptoServiceProvider().GetBytes(salt = new byte[16]);
var pbkdf2 = new Rfc2898DeriveBytes(PasswordTextbox.Password, salt, 10000);
byte[] hash = pbkdf2.GetBytes(20);
byte[] hashBytes = new byte[36];
Array.Copy(salt, 0, hashBytes, 0, 16);
Array.Copy(hash, 0, hashBytes, 16, 20);
string savedPasswordHash = Convert.ToBase64String(hashBytes);
return savedPasswordHash;
}
然后我尝试使用此功能将其与用户输入进行比较:
public static void UnhashPassword(string hashedPassword, string hashedPasswordFromDatabase)
{
byte[] hashBytes = Convert.FromBase64String(hashedPasswordFromDatabase);
byte[] salt = new byte[16];
Array.Copy(hashBytes, 0, salt, 0, 16);
var pbkdf2 = new Rfc2898DeriveBytes(hashedPassword, salt, 10000);
byte[] hash = pbkdf2.GetBytes(20);
for (int i = 0; i < 20; i++)
if (hashBytes[i + 16] != hash[i])
throw new UnauthorizedAccessException();
}
第二个函数总是抛出异常。不确定是什么原因,因为这个答案似乎对其他人的问题都有效。
答案 0 :(得分:2)
如果没有能够可靠地再现问题的好Minimal, Complete, and Verifiable code example,就不可能肯定地说出错了。但是,以下代码示例 完全按预期工作(即result
的值在true
被ValidatePassword()
调用初始化之后为static void Main(string[] args)
{
string password = "password";
string hashedPassword = HashPassword(password);
bool result = ValidatePassword(password, hashedPassword);
}
static string HashPassword(string password)
{
byte[] salt;
new RNGCryptoServiceProvider().GetBytes(salt = new byte[16]);
var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000);
byte[] hash = pbkdf2.GetBytes(20);
byte[] hashBytes = new byte[36];
Array.Copy(salt, 0, hashBytes, 0, 16);
Array.Copy(hash, 0, hashBytes, 16, 20);
string savedPasswordHash = Convert.ToBase64String(hashBytes);
return savedPasswordHash;
}
static bool ValidatePassword(string password, string hashedPasswordFromDatabase)
{
byte[] hashBytes = Convert.FromBase64String(hashedPasswordFromDatabase);
byte[] salt = new byte[16];
Array.Copy(hashBytes, 0, salt, 0, 16);
var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000);
byte[] hash = pbkdf2.GetBytes(20);
for (int i = 0; i < 20; i++)
{
if (hashBytes[i + 16] != hash[i])
{
return false;
}
}
return true;
}
}:
HashPassword()
上述内容与原始代码之间的唯一重大变化是password
方法使用传入的PasswordTextbox.Password
值,而不是PasswordTextbox.Password
。
基于这种观察,我只能猜测,在你自己的场景中,你并没有像以后验证那样使用相同的密码。这是因为$array = SELECT ...;
foreach ($array as $item)
{
do some SQL with $item
}
从来没有使用过正确的密码,或者您之后传递了不同的密码,我无法说出来。
如果上面的代码示例没有充分指出您正确的方向,以便您可以使代码正常工作,请改进您的问题,使其包含一个好的MCVE。