masterwok
masterwok

Reputation: 5131

How to generate hash using specified salt and password in asp.net Identity?

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

Answers (3)

Scott Chamberlain
Scott Chamberlain

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

Suhas Joshi
Suhas Joshi

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

meziantou
meziantou

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

Related Questions