I was just going through one of DavidHayden\'s articles on Hashing User Passwords.
Really I can\'t get what he is trying to achieve.
Here is his code:
<
If you dont use asp.net or .net core there is also an easy way in >= .Net Standard 2.0 projects.
First you can set the desired size of the hash, salt and iteration number which is related to the duration of the hash generation:
private const int SaltSize = 32;
private const int HashSize = 32;
private const int IterationCount = 10000;
To generare the password hash and salt you can use something like this:
public static string GeneratePasswordHash(string password, out string salt)
{
using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, SaltSize))
{
rfc2898DeriveBytes.IterationCount = IterationCount;
byte[] hashData = rfc2898DeriveBytes.GetBytes(HashSize);
byte[] saltData = rfc2898DeriveBytes.Salt;
salt = Convert.ToBase64String(saltData);
return Convert.ToBase64String(hashData);
}
}
To verify if the password which the user entered is valid you can check with the values in your database:
public static bool VerifyPassword(string password, string passwordHash, string salt)
{
using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, SaltSize))
{
rfc2898DeriveBytes.IterationCount = IterationCount;
rfc2898DeriveBytes.Salt = Convert.FromBase64String(salt);
byte[] hashData = rfc2898DeriveBytes.GetBytes(HashSize);
return Convert.ToBase64String(hashData) == passwordHash;
}
}
The following unit test shows the usage:
string password = "MySecret";
string passwordHash = PasswordHasher.GeneratePasswordHash(password, out string salt);
Assert.True(PasswordHasher.VerifyPassword(password, passwordHash, salt));
Assert.False(PasswordHasher.VerifyPassword(password.ToUpper(), passwordHash, salt));
Microsoft Rfc2898DeriveBytes Source