views:

662

answers:

8

I have a database of hashed passwords that had no salt added before they were hashed. I want to add salt to new passwords. Obviously I can't re-hash the existing ones.

How would you migrate to a new hashing system?

+16  A: 

Sure you can. Just add a salt to the existing hash and hash it again. Of course this will require any future logins to go through the same process meaning two hash functions will need to be called but lots of legitimate patterns do this anyway so it doesn't smell as bad as you might think.

Salting a password is an effort to defend against rainbow tables. In this case the salt does not need to be a secret.

http://en.wikipedia.org/wiki/Rainbow_tables#Defense_against_rainbow_tables

You can actually see in the article

hash = MD5 (MD5 (password) . salt)

Which is the same exact method you would be using. (Except a different hashing function.)

Spencer Ruport
+1 - I like this better than what I was thinking
John Rasch
Interesting idea. Are you sure it doesn't hinder the security somehow, though? Especially that this way, a person obtaining the strings after they the second hash will have a lot of information about the previous step (like constant length, for example), which might allow him aid him find the salt.
Sinan Taifour
Salts aren't secrets. In fact you need to save them (in plain text) along with each user.
Spencer Ruport
I was in the process of writing an answer to this question saying "You can't do this", when I read your clever solution. Nice job +1
Graeme Perrow
+1  A: 

You could add a column, consisting of a flag showing whether the user has an old (no salt) or a new (with salt) hash.

A good idea is, at that point, to force all users to change their passwords upon sign in. This way you can get rid of that column eventually.

Sinan Taifour
or have the column as hash_type(nosalt, md5, sha1, sha512). If it's 'nosalt', do one thing, if its others, there's a salt column used and stored elsewhere in the row to use in the comparison - with the appropriate hash function when you come to upgrade to it (as MD5 is already seeming weaker).
Alister Bulman
+11  A: 

As a quick fix, you could create a salt column in the database, and when a user logs in correctly matching the old hash, you can then use that password that they entered with a salt and create a new hash.

John Rasch
ooo, that sounds like a damn good idea
Allen
This would be my approach as well. Refactoring definitely extends past code and can - actually, *needs* - to be done on the database level, as well.
joseph.ferris
+1, excellent scheme.
nik
The problem with this is that it presumes that the user will login eventually, which may not be true. Meanwhile their password is much more open to attack. If you couple that with the fact that people reuse username's and passwords frequently...you should go with Spencer's solution.
Flory
A: 

There are some ways here that may work for you.
Remember, any constant pattern you add into the existing hash is useless (one of the tricks on that link is suggesting something like that). There should be no identifiable pattern that can be used to isolate the salt.

Of course, the best way would be to migrate to a salted hash table.

nik
A: 

Create a new field in you're database named "salted" with a type of true/false (or whatever the equivalent is in your DBMS). Set all the values to false for the existing hashes. Whenever a new, salted, hash is added, set the "salted" field to true.

Then, all you have to do is handle the two types of hashes differently in your code.

This is more of a general solution than a specific one, but it should solve your problem.

Cameron
A: 

If you are storing the salt inside the hash, it should be fairly straight forward to determine if a salt is included by checking the length of the hash. If there isn't a salt, just hash the password, if there is a salt, hash the password + salt.

You shouldn't need a boolean column in your database.

NerdFury
A: 

The best way I store my salt is that I embed the salt value within the password hash + salt I have just created. I don't append the salt string to the beginning or end of the hash, I literally embed the salt into the hash.

D. M.
A: 

I dealt with a similar issue involving multiple hashing techniques. I used the approach of encoding a hash method type in the database as well (i.e. 'alpha', 'beta', 'gamma', 'delta'). I marked all current hashes with the appropriate level. As users logged in, I validated their passwords and re-hashed them using the updated methods. Our passwords expire after 90 days, so it was just a matter of holding on for 3 months until all passwords using the old methods could be reset.