9
votes

I am working on a system that has been hashing user passwords with MD5 (no salt). I want to store the passwords more securely using SHA-512 and a salt.

While this is easy enough to implement for future passwords, I'd like to also retrofit the existing MD5 hashed passwords, preferably without forcing all the users to change their passwords. My idea is to just use SHA-512 and and an appropriate salt to hash the existing MD5 hash. I can either then set some flag in the database that indicates which passwords were hashed from plain text, and which ones were hashed from an MD5 hash. Or I could just try both when authenticating users. Or even just hash new passwords with MD5 and then SHA-512/salt, so they can be treated the same as old passwords.

Programmatically, I don't think this will be a problem, but I don't know enough about encryption/hashing to know if I'm compromising the quality of the hash in any way by applying a SHA-512/salt hash to a password that was already MD5 hashed. My first instinct is that if anything, it would be even stronger, a very light key stretching.

My second instinct is that I don't really know what I'm talking about, so I'd better get advice. Any thoughts?

4
SHA-512 will offer very little improvement over MD5 (eg: MD5(salt + password) is practically equivalent to SHA512(salt + password)). General purpose hashing functions like MD5 and the SHA family were not built to store passwords. Use bcrypt.NullUserException
Very true. I actually intended to do key stretching, but didn't make that clear in my question. I ended up using PBKDF2 instead of naively implementing my own key-stretching algorithm.Jeremiah Orr

4 Answers

5
votes

Function composition with cryptographic primitives is dangerous and should not be done if avoidable. The common solution for your type of problem is to keep both hashes for a migration period, using the new hash where possible and transparently upgrading old passwords (when you check a password and it matches, rehash it with the new algorithm and store it)

This won't work if you have a challenge-response based scheme where you don't get to see the plaintext password, but since you seem to have a stored salt that does not change, I assume your application does the hashing.

4
votes

If you hash with MD5 first, you will only have the spread of MD5 (128 bit). A large fraction of the space of SHA512 will not be covered by your passwords. So you don't take advantage of SHA512, but it won't be worse than MD5.

You have the benefit that if someone obtains the SHA512 hash and doesn't know the salt (this you have to enforce somehow) can't look up the hashes and get the passwords -- something that would be possible with the MD5 database you have now.

So yes, you can just rehash the existing MD5 passwords. But as explained in the first paragraph, it would be a bad idea to apply MD5 to all new passwords as well and then hash them as SH512. A easy implementation would be to have a boolean 'salted' field in the database next to the hashes (but don't put the salt there).

1
votes

Trust your second instinct. Use an existing library made especially for hashing passwords instead of trying to cook up your own.

Probably hash your new passwords with MD5 and then hash the MD5 with your password hashing library. That way, you can maintain backwards compatibility with your old passwords.

I.e. password_hash(All old, md5'd passwords) and password_hash( md5(New passwords) )

(Warning: I'm not a cryptography expert)

http://www.codinghorror.com/blog/2007/09/youre-probably-storing-passwords-incorrectly.html

0
votes

If you look at how most Bank and high security people does there password changing. Most of them basically ask people who is using the old encryption method to create a new password. I think you first solution of placing a flag on all existing old MD5 password users, and notify them they need to create new password and slowly migrate them to the new system. That way when you trouble shoot the system if anything goes wrong you won't be asking is this a new user or an old one. Are we double hashing or single? Should never compare two hash as a possible answer because what if MD5('abc') => 123, SHA('NO') => 123, that means someone could have typed in the wrong password but still gets in.