prevent past used passwords while changing

I am developing a web application using ASP.NET, VS 2008, framework 3.5
I am using sql membership provider for user authentication.
When a user is changing his password, I want to prevent him using previously used passwords.
How to implement this ?
Who is Participating?
Assuming you are using a hashed password format you could add a new table, let's say "UserPasswordCache" where you can store the recently used password hashes alongside the users' primary key and see if you get a match there when a user tries to set a new password.
vu3lmgAuthor Commented:
I am thinking of doing that,  just wanted to know if there is an easy way around .
Any examples or code downlodable from the net ?
Just hook into ValidatingPassword event of the MembershipProvider class and store a MD5 or SHA hash of the password in your password history there if it's succesful. Also check if you're dealing with a valid and really new password there.
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

vu3lmgAuthor Commented:
In the ValidatingPassword  event, args.Password property returns unhashed-new-password.
In the history table old passwords are stored in the hashed format.
How do I compare these ?
The membership provider does some funky stuff in the hashing procedure. Please test attached code and see if it works, really not sure here. You need to store the salt used for hashing the individual passwords,retrieve and pass it to the method below. Do this for every password stored in your history.

Another approach would be to not store the membership provider hash in the history but a hash generated by you that is more easily to reconstruct. But before you do that make sure you evaluate the security implications.

public static bool ComparePasswordHashes(string newPassword, string saltValue, string oldPasswordHash)
  byte[] saltValueBytes = System.Convert.FromBase64String(saltValue);
  byte[] plainTextBytes = System.Text.Encoding.Unicode.GetBytes(newPassword);
  byte[] saltValueBytesWithPlainTextBytes = new byte[saltValueBytes.Length + plainTextBytes.Length];
  System.Buffer.BlockCopy(saltValueBytes, 0, saltValueBytesWithPlainTextBytes, 0, saltValueBytes.Length);  
  System.Buffer.BlockCopy(plainTextBytes, 0, saltValueBytesWithPlainTextBytes, saltValueBytes.Length, plainTextBytes.Length);
  byte[] hashBytes = new System.Security.Cryptography.SHA1CryptoServiceProvider().ComputeHash(saltValueBytesWithPlainTextBytes);
  string computedHash = Convert.ToBase64String(hashBytes);
  if (computedHash == oldPasswordHash)
    return true;
    return false;

Open in new window

vu3lmgAuthor Commented:
To avoid all this conversion (Hashing the password) I decided to do following (let the provider Hash the password and I deal with hashed passwords only).

* I created a table called "Password History" to store current and past password Hashes for each user.
* I modified the "aspnet_Membership_SetPassword" to do 2 things.
          1) Check the "Password History" table for matching Password Hash, if found return failure, do not Set the new password.
          2) If the password is not a repeat, store the password hash in a "Password History" table for future comparision, return success.

It seem to be working fine.  
Any comments / suggestions on this.
I will wait for your comments before closing the question.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.