If you have ever used an encryption hashing algorithm--such as MD5 or SHA1--before, you will have noticed that the number of characters in the output are constant. You find this as a good thing: it's impossible to guess to the original length; and you can store it in a database and know exactly how long it will be. But, with all good things, come the bad. In this case, the bad is something called "collisions."
Collisions are simple: the mean that two or more inputs can have the same output. If you have ever studied parabolas in math, then you know how collisions can be interesting.
Collisions are a bigger problem when dealing with passwords and encryptions. The common way of storing a password is by encrypting it by MD5; when the user logs in, check it with the hash. While this is usually effective, it can cause problems. Remember that collisions exist in hash functions--that means that there is another phrase (and infinite amount of phrases) out there that will generate the exact same hash. What does that mean? Well, it means that you just have a lot of passwords to choose from!
So, why am I telling you this? Although finding a collision is quite hard, it can be magnified. Take this for an example: say the output is abcdefg. Now, let's say that 123 and 987 will both produce abcdefg when ran through the MD90000 function. This means that a user may enter 123 or 987 into the password field and be authenticated. The PHP code:
Now, let's say that we want to be even more secure. We know that 123 becomes abcdefg, and we also know that running abcdefg through the hash function will produce qwertyu. Nevertheless, poiuytr will ALSO produce qwertyu. So, at first glance we decide to do:
$hash = md90000('123');
$hash2 = md90000('987');
// hash = hash2
Do you know the problem? I will do my best to illustrate:
$hash = md90000(md90000($pass))
123 will become abcdefg,which will become qwertyu.
987 will become abcdefg, which will become qwertyu.
Now, we can also say:
456 will become poiuytr, which will become qwertyu.
789 will become poiuytr, which will become qwertyu.
Now do you see the problem? By running our password through the encryption twice, we have just doubled the number of collisions possible. We run it through it a third time, and it increased by 6x. Do it a thousand times, and pretty much everything would equal the hash.
The lesson here: do not encrypt an encryption hash. While you may think it protects you against brute forces, it creates many more collisions.
What about doing something like:
Still a bad idea; md5 and sha1 both have collisions, and you are still doubling the amount of them.
$hash = sha1(md5($pass));
So what can you do? You can combine encryptions, which will reduce collisions:
While two passwords may produce the same MD5 result, they are unlikely to produce the same result in SHA1 too. Thus, that collision was destroyed.
$hash = sha1($pass).'-'.md5($pass).'-'.encrypt($pass);
$hash = md5(sha1($pass)); // BAD
$hash = md5($pass).'-'.sha1($pass); // GOOD