views:

142

answers:

4

Wondering whether it matters if a salt is unique for a single given user each time the password is changed, or whether it's not a big deal to reuse the same salt each time.

I currently generate a new random string as the salt each time a given user updates the password. This way each time the user has a new password their is also a salt change. It's easy to do, so why not.

Well... here's why. I need to store the previous X passwords to ensure a password is not reused. In the old days (the last time I wrote code for this), I could just store previous MD5 hashes, and compare new ones to that list. Well, now that I am using salted hashes where the salt is unique each time, those comparisons are no longer possible as the previous salts are no longer known.

To make that system work, I have two choices: store a history of the salts in addition to the final hashes, or reuse the same salt for any one given user with each password update. Either of these would allow me to build values that could be compared to a history.

The latter is less work, but does it lose any strength? From a practical standpoint, I don't see that it does. Thought I'd get a second opinion here. Thanks.

To keep the question "answerable" -- would reusing the same salt for any one user have an acceptably minimal reduction of protection in order to maintain a searchable password history (to prevent pswd recycling)?

+6  A: 

Reusing the same salt means that if a user is explicitly targeted by a hacker, they could produce a "password to hash" dictionary using "the user's salt" - so that even if the user changes their password, the hacker will still immediately know the new password without any extra work.

I'd use a different salt each time.

As for storing the MD5 hash plus salt - presumably you're already storing the salt + hash, in order to validate the user's current password. Why can't you just keep that exact same information for historical checks? That way you can use one piece of code to do the password checking, instead of separating out the current and historical paths. They're doing the same thing, so it makes sense for them to use the same code.

EDIT: To explain what I mean, consider a 4 character salt, prepended to the password... and for the sake of argument, imagine that someone only uses A-Z, a-z and 0-9 in their password (and the salt).

If you don't know the salt ahead of time (when preparing a dictionary attack) then in order to prepare a dictionary for all 8 character "human" passwords, you need to hash 62^12 concatenated passwords. If, however, you always know what the first 4 characters of the concatenated password will be (because you know the salt ahead of time) then you can get away with only hashing 62^8 values - all those beginning with the salt. It renders the salt useless against that particular attack.

This only works with a targeted user of course - and only if the attacker can get at the hash list both before and after the password change. It basically makes changing the password less effective as a security measure.

Jon Skeet
I don't see how the 'attacker' would know the new password. If I had a hash, that is of H(A+S), and then I get the new hash: H(B+S), how can I immediately determine B?
Noon Silk
@silky: If you know S ahead of time, you can prepare a dictionary attack using that salt. It cuts down the number of possible (B+S) values to consider.
Jon Skeet
Jon: Well obviously. But how did the attacker get hold of S, and not the new S? If he can't get hold of the new S, how did he get hold of the hashed password? I don't think that's a realistic case.
Noon Silk
He can get hold of the new S - but only *after* the password has been changed. That means he's got to solve the hash before the password is changed again. If the salt is reused, he can solve the hash for *future* passwords *before* the password is changed.
Jon Skeet
Right. I follow you now.
Noon Silk
@Jon -- that's pretty much what I was thinking, but it covers a pretty narrow case where someone got the user data table, focused one user, then continued to get the user data table frequently enough, or with just the right timing to do it all over again. Seemed pretty slim. However, I went ahead and built the code to hash the new pswd with all previous salts to compare to all previous hashes.
gw
+1  A: 

Another reason for using salt in password hashes is to hide the fact that two users use the same password (not unusual). With different hashes an attacker won't see that.

tangens
The question is about historic hashes for the same user, not shared for all users.
Kobi
A: 

Firstly, stop using MD5 (if you are using it), and use SHA-2, MD5, SHA-0, and SHA-1, are all dead hashes.

-- Edit:

I now agree with Jon Skeet, and suggest you consider generating a new salt with each password change. It covers a small case where the attacker may get the salt+hash, then not be able to gain access again, but will still allow him (with some guessing of how you combine them), to calculate what the hashes could be for all future passwords. It's very small, and is not so important, because the password sizes will need to be significantly small (say, 8 chars) for even calculating them all offline to be practical. Yet it exists.

Secondly, to consider whether or not it matters, we need to think about the purpose of salts. It is to prevent offline attacks against someone who has a complete listing of only the passwords.

On this basis, if the salt is equally "difficult" to obtain before and after password changes, I see no use a new salt (it's just as at-risk as it was before). It adds additional complexity, and in implementing complexity is where most security problems occur.

Noon Silk
Hmmm "stop using MD5...and use... MD5..." ;-) Yeah, my refc to MD5 went with "old days" as in long time ago when it was still safe. Using better stuff now, and rather long salts. The attacker can have (will pretty much always have) the complete listing of the salts too--not only the passwords. Changing the salt each time makes the attacker have to regenerate the rainbow table for a specific user rather than reuse it, so that's why it is useful.
gw
A: 

I might be being incredibly dim here, but, where would you store the salt that would be inaccessable to someone with enough access to get the hashed password.

James Anderson
The salts are stored right next to the hashed passwords (probably on the same row), the attacker gets them too, but need to spend a lot of time trying to find a match (for any user, or for a specific user).
Kobi
The theory is that there's really not much practical added value in separating them. The existence of the salt makes pre-calculated rainbow tables useless. So someone now has to calculate a new rainbow table from scratch with the added depth of the salt (and various ways to use the salt: prefix, suffix, split, interlaced, etc). Even if you know the salt, the cost in time and resources to calculate this new table is simply too high to bother. Someday SkyNet will start to calculate and store all permutations, but before it finishes either it or we will be extinct and it won't matter. ;-)
gw