10

I have an application with a user database. The database stores the password using a bcrypt hash with a randomized salt.

How can I implement a password history set (to prevent password reuse) in a case like this?

If I have the traditional 3 field password reset (enter current, enter new, confirm new) I could store the current one as I replace the old with the new. However, then I have the case of a forgotten password. My users could go and do an self-service auto reset and reuse their passwords over and over again.

The stored passwords would be encrypted, but with reversible encryption making them less secure.

Adi
  • 43,808
  • 16
  • 135
  • 167
Snowburnt
  • 203
  • 2
  • 6

3 Answers3

16

Store the old salt and hash values. Hash the new input with any old salts and see if they match.

If it worked for checking the password when they logged in normally, it will work for checking if the password has been used before too.

AJ Henderson
  • 41,816
  • 5
  • 63
  • 110
  • 3
    wow, I completely over-thought this one. – Snowburnt Dec 31 '13 at 15:29
  • @Snowburnt - yeah, we all do that from time to time. Glad I could help. – AJ Henderson Dec 31 '13 at 15:48
  • There's some concern that by storing the old hashes, you're giving someone who steals your password db the opportunity to make an offline attack on old passwords, which could conceivably harm the user or lead to a guess at the current password (https://security.stackexchange.com/questions/85074). I suppose perhaps you could make a Bloom filter of the old hashes or something, at the cost of false positives, with the parameters set such that someone trying to guess old passwords using the filter will find far more false positives than true ones. – Steve Jessop Apr 02 '15 at 23:23
  • @SteveJessop If a user's old passwords are crackable, and they're changing their password based on a simple pattern, it's fairly likely the new password is just as crackable as the old one. So, I'm not really seeing any value in dumping the old for that case. As for password reuse concerns, these tend to be largely mitigated by the password expiration itself. Unless it's fairly close in sync with another password-based authentication system's cycle, chances are the exact same password isn't going to be reused. – Iszi Feb 24 '16 at 23:05
5

If password1 = password2, then hash(password1, salt1) = hash(password2, salt1).

In other words:

  • Bcrypt the new password with the same salt and iteration count.

  • Compare the hashes.

  • If the new hash is different from the old hash, then everything is okay (according to your criteria), and you can simply re-hash the new password with a new unique salt and store it in the database.

  • If the new hash is the same, then the new password is the same as the old password. Tell your user to choose a new one.

Adi
  • 43,808
  • 16
  • 135
  • 167
1

My users could go and do an self-service auto reset and reuse their passwords over and over again.

To address this concern raised in the original question you would have to store more than just the last password. This can be easily done by storing the previous n salts and hashes. However, this may not be a good idea.

One way to ameliorate this would be to store similar passwords, in addition to the actual passwords.

Another way would be to only store part of the hash.

Of course, you could use both approaches.

go2null
  • 111
  • 3