PHP: Correct Hashing Passwords in PHP

I found this article about password hashing in PHP on Twitter and found a few serious points that are not fully correct in this article.

Rehashing is good

First, the advice "not to rehash" is wrong:

Double hashing is *worse* security than a regular hash

The idea behind the advice goes like this:
md5(md5(md5(md5(md5('password'))))) = '7b3b4de00794a247cf8df8e6fbfe19bf'
Now "Ghogilee" and "Clay Lua" think, they only need to find a collision that goes like this:
md5(?) = '7b3b4de00794a247cf8df8e6fbfe19bf'
Whats wrong about this theory?
They do not need a collision for the last md5(), they need a collision for the whole md5(md5(md5(md5(md5(?))))) because the application will always do 5 md5() for checking passwords.
So, if you hash your hashes multiple times, it will not make them more secure in first place. It will make brute forcing them slow as hell!

Lets do some math to point out why the advice is wrong.
A MD5 hash is always 32 hexadecimal chars long. This means, there are 16^32 (= 3.4 x 10^38) possible combinations. That is a number with 38 zeros!
Now, lets search password char-set and length with a similar combination range.
I took "a-zA-Z0-9" for char-set, which are 62 unique chars. I know there are also special chars, but this is only for demonstration.
The two password lengths close to 10^38 are this two:
62^22 = 2.7x10^39
62^21 = 4.3x10^37

This means the password needs to be at least 21 chars long to have the same number of possible combinations like a MD5 hash.
An example for such a password:
Do you think such a password is weak? I do not so.

Hashes do not contain information

Second, a hash does not contain "information" or "data".

sha1(md5($pass)) makes even less sense, since you’re feeding in 128-bits of information to generate a 256-bit hash, so 50% of the resulting data is redundant. You have not increased security at all.

They are right when they claim that a longer password is more secure. But it is clear, that a hash does NOT contain some sort of "information". A hash is like a fingerprint, a relation from password -> hash. NEVER the other way round. Your fingerprint does not contain data about your body or mind, it is just a relation from human -> fingerprint.
So telling a sha1 from a md5 is insecure, is dead wrong.

SHA2 is not the answer to the common password problem

Third, using SHA2 is NOT the answer to the common problem.

Many of us should start moving forward to new hash function rather than sticking on to MD5 and SHA-1. Although it is still secure for these two algorithm to be used given a strong password. Nonetheless, in the near future these two might not be that secure anymore. Furthermore, both algorithm had already been dropped by US and focus on SHA-2 instead.

Just switching from MD5 and SHA1 to SHA2 will not remove the common problem with these methods.
A normal attacker does not have the cryptographic knowledge and hardware to perform a intelligent collision attack. It is not his aim, he only want to get data he can use for making cash like email / paypal accounts and credit card information.
The main problem in hash methods is, they are just relations. The md5/sha1/sha2 from "dog" will always be the same. The attacker does know that so he just starts his brute forcing program and waits. Even using salts does not change his behavior because he got the salt too with his SQL-Injection / Dump / Attack. It may just take a little bit longer to get some results.
So just using simple hashed md5/sha1/sha2, even with salt will make our attacker happy because it is just a matter of time.

My Advice

If you want to create secure password hashes, take a look at my secure_hash class. This class can uses random salts, global salts, permutations, random iterations and you can create own hashing functions.

Related posts:


Ein Kommentar zu “PHP: Correct Hashing Passwords in PHP”

  1. bucabay 21. Oktober 2009 um 00:53

    Key strengthening (double hashing) seems to be a common use:

    Also talked about here: