I read a lot about how md5 is hacked and don’t use it for passwords blah blah blah
It is true that finding collisions in md5 is easy enough and brute forcing them with modern day computers is trivial.
But are they useless?
I Don’t Think So!
The following is based on someone getting access to your database because say you left the door open and they were able to inject some sql which revealed your user accounts. Sadly a very common occurrence.
The reasoning for not using md5’s as password hashes goes like this. I can brute force 5 Billion Hashes a second therefore I can crack all your passwords within minutes therefore md5 is terminally broken.
Well Yeah, That is correct if you don’t salt your hashes and you should! What is salting? Salting is adding random characters to the password to increase its complexity. It is done by the webserver or whatever program is using the password
It goes like this..
instead of
hash = md5(password);
you have
hash = md5(password . salt) ;// . means concatenate
Now if the cracker doesn’t have the salt he cannot brute force your password and rainbow tables and collisions are also out. (rainbow tables are massive precomputed tables of cracked hashes)
The trouble with the above solution is two users with the same password have the same hash. That little leakage of information could be enough to crack the password.
So what you need to do is to add a unique salt, one per password. This then prevents two passwords having the same hash.
hash = md5(password . unique salt);
But this means you need to store your unique salt with your password. So if your database is hacked then your salts are also known! But it does give the bad hacker a headache they still need to brute force every password in your database with a different salt for each password. It makes it exponentially harder.
How about we add another salt to the system will that help? Yes it will!
If you add a third common salt to the system so that your algorithm now becomes
hash = md5(password . unique salt . common salt);
Then the bad hacker needs all three. As long as the hacker does not get the common salt then your passwords are safe. BUT DO NOT STORE THE COMMON SALT IN THE DATABASE!
If they have the database and get your common salt because you were silly enough to store it there then you are back to the salt plus unique level of complexity. Good but not great!
Remember this too, as a developer we can do all we want to protect our users passwords. But if users are stupid enough to use simple passwords and then share them across multiple sites then they deserve to get hacked.
To protect them from themselves when setting passwords for users always set a minimum complexity.
So go ahead and use md5 in the knowledge you are reasonably safe. Of course if they get access to your server then once again you are in trouble!
So the solution is two salts a unique and a common salt stored in a different media (configuration file)
AND insist on minimum complexity passwords.
md5 Is fast and that’s why its still a good choice for a busy server.
Of course you may have different reasoning so I’d love to hear it.
P.S. If you really want to give your bad hacker a hard time then add a counter to your hashing algorithm.
hash = md5(password . unique salt . common salt); for (i = 0 to 1000000) { hash = md5(hash); }
June 11th, 2014 on 10:52 am
if you say that md5 are not secure enough (which is true), meaning you can get the passwords if you got the md5 hashes, right?
so i dont think
hash = md5(password . salt)
is the solution
because the hacker just needs two users (or even one if the password is easy enough) to get the salt.
what i mean is, if my password is pass1234 and the salt is xyz
so my hash is md5(pass1234xyz), the hacker takes the hash and turn it back to “pass1234xyz”.
if he does it for two users, he can see that the salt is xyz and still get all the other passwords easily…
so… whats the solution?
June 13th, 2014 on 3:43 pm
Hi Moti
I agree if you use a simple common salt like ‘xyz’ and don’t include a per user salt.
by using two salts, one per user which by definition must be stored in the database and one “master’ salt this weakness is totally alleviated.
When I create the per user salt I usually md5 a couple of things such as time and a random number or perhaps time and the users email address. it doesn’t really matter.
Then the master salt can be anything really as long as it has a reasonable length
So your would be hacker need to crack a hash generated from a string in excess of 40 characters long and then somehow find both the master hash and the per user hash
By having a master hash the password can’t be cracked even if the hacker has full access to the database.
If they have full access to your server then you are toast no matter what you put into practice.