In this article I will explain the method I suggest for hashing password and saving them in a database.

First of all, never insert passwords to the database as plain text!
If your database is stolen your users will pay the price (maybe you will have to pay them for the damage you have caused).

The easy and common solution for this particular problem is to use an one-way hash function, such as md5 and sha1, which takes the password and encrypts it.
Unfortunately, this method is not as strong as you may think.
Nowadays hackers can use rainbow tables to reverse almost any password hashed with these algorithms in no time.
True, it takes a couple of hours to create an extensive rainbow table; however it takes a couple of minutes or even less to crack almost any password once the rainbow table is ready!
Moreover, there are many other attacks that can crack these hashes pretty fast.

To understand how you can protect yourself from rainbow tables and many other attacks using salts and a better algorithm, you should first understand what a rainbow table is.
Basically, a rainbow table is just a collection of all possible passwords (or all probable password) encrypted and stored in a way that is optimal for reversing hashes.
If we have to hash one password every few seconds or even less, the hacker has to hash every possible combination (for a 10 digits a-z and 0-9 password there are 3710 [about 4.8x1015] different combinations) as fast as possible, which takes them a couple of hours for algorithms such as md5 and sha1.

We can protect our password from rainbow tables and similar attacks by using salts.
A salt is an unique (and usually random) string that is added to every password before it is encrypted. It is worth mentioning that the salt doesn’t have to be highly random, but it must be different for each password.
If our salts are long enough, using rainbow table is impractical, even if the hacker knows both the hash and salt of each password.
The hacker can either create a different rainbow table for each password, which takes a few hours for each password and therefore impossible, or create a huge rainbow table, which will take hundreds of years to be created on modern computers and increase the look up time to hours rather than minutes.

We can, and should, make it even harder for the hacker.
Rather than hashing the password once, we can hash it thousands of times, with an algorithm that takes longer to run, for example sha512.
We will not feel the difference as our server barely hashes password, however the hacker has so many passwords to encrypt, no matters what hacking method he chooses.
For example, if we chose to use sha512 10,000 times rather than sha1, each password will take about 15,000 times longer to be created, about 30 password / second instead of 500,000 password / second!
So if it took the hackers a couple of hours to generate a rainbow table for sha1 (say 3 hours), it will take them about 5 years to generate a rainbow table for 10,000 runs of sha512!
Slowing the algorithm makes different brute force attacks, including rainbow tables, extremely inefficient thus impossible to use.

To sum the theoretical part of this article up, combining these two methods will protect your users’ password much better than regular md5 or sha1 hash.
Implementing this two ideas is not as hard as you may think, and here is the explanation for PHP.

Luckily PHP provides a function that does almost everything for us, the function crypt.
This function can encrypt passwords with few popular algorithms, I will focus sha512. If we use sha512 the salt should be 16 characters from the alphabet “./0-9A-Za-z”, a longer salt will be trimmed.

The following code will hash the password “not_a_real_password” with the salt “too_long_salt_is_used123″, using sha512 ($6$) 10,000 times (rounds=10000$): echo crypt('not_a_real_password', '$6$rounds=10000$too_long_salt_is_used123$'); // output: //$6$rounds=10000$too_long_salt_is$ewdGWdAWWX.x4lR7JZaeQTzAVOlZ70li8fu7MGFaIvN6sQ9J36l9sV5OKOGbMU4yut2RkjZhyQC0jg6HT3gFF.0.091614961624146 As you can see the algorithm indicator, the number of rounds and the salt are returned with the hashed value (even though the salt was trimmed to 16 characters). You should store that result right in the database without changing it, cracking this data is almost impossible. What we now need is a simple function to create a random salt: function generate_salt() {$dictionary = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$dictionary_size = strlen($dictionary);
$salt = ''; for($i = 0; $i &lt; 16;$i++) {
$salt .=$dictionary[mt_rand(0, $dictionary_size - 1)]; } return$salt;
}

Now, assuming we have a variable named $password and we want to hash it we simply call: crypt($password, '$6$rounds=10000$'.generate_salt().'$');

Assuming we have a variable named $password and a hashed password named$hash and we want to compare them we simply call: