Reputation: 5131
I am currently using the new ASP.NET Identity framework.
I must implement a way of checking if a password the user wishes to change their password to has been used in the past. I have a table containing retired hashes and their corresponding salts.
What I am unable to figure out is how to generate a hash using a specific salt so I can compare the new password to the retired passwords. I've seen UserManager.PasswordHasher.HashPassword(password) but I don't see an overload to specify the salt.
How does one go about hashing a password with Identity and specify a salt?
Upvotes: 2
Views: 11207
Reputation: 127543
Just verify the password the same way you would verify currently. All you need to do is store the same information you would store for the current password in the old passwords and check that none of them verify
bool UserReusedPassword(string username, string password)
{
foreach(string oldHash in GetOldHashesForUser(username)
{
if(UserManager.PasswordHasher.VerifyHashedPassword(oldHash, password) != PasswordVerificationResult.Failed)
{
return true;
}
}
return false;
}
using UserManager.PasswordHasher
the salt is stored as the first few bytes of the hashed string, so you should not need to "manually enter the salt" VerifyHashedPassword
will automatically read it in and set it for the verification process.
Upvotes: 5
Reputation: 1060
You can look at the migration sample from SQL membership to Identity here. SQL membership used password salt for encryption and the article outlines hooking in a custom password hasher to reuse those passwords.
Upvotes: 0
Reputation: 21337
You can't use a specific salt. However you should use a different salt for each password. So your HashPassword method is responsible of the generation of the salt. Here's an example (mainly inspired from the Mircosoft default implementation):
public string HashPassword(string password)
{
if (password == null) throw new ArgumentNullException("password");
int saltSize = 16;
int iterations = 4000;
byte[] salt;
byte[] bytes;
using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, saltSize, iterations))
{
salt = rfc2898DeriveBytes.Salt;
bytes = rfc2898DeriveBytes.GetBytes(32);
}
byte[] inArray = new byte[saltSize + 32];
Buffer.BlockCopy((Array)salt, 0, (Array)inArray, 0, saltSize);
Buffer.BlockCopy((Array)bytes, 0, (Array)inArray, saltSize, 32);
return Convert.ToBase64String(inArray);
}
As you can see the salt is embedded in the result of the HashPassword method so when you need to validate the password, you can extract the salt and the hash and make the verification.
Upvotes: 4