I have read tons of questions and tutorials about encrypting a password, and while I've learned a lot, nowhere did I find an answer to this.
I want to use crypt() for hashing a password that I will store on Database. I also know I need to use a salt so it works properly, and I've read that the best way to generate a random salt is by using this or something similar.
If I understood correctly the process is this:
But then how do I recover the salt when user tries to login?
In a few questions I've found, one of the answers was to store the randomly generated salt on the database. But I thought the whole purpose of salting was to be more secure, if an attacker got access to my DB he would see the 'salt' fields and even if my passwords are encrypted he would gain easy access to accounts.
Other answers said that the 'salt' is prepended to the password when using crypt() so there is no need to store it in a separate field. My question is, how do I get access to it? Is there some function that does this and I'm totally missing?
You store the salt in your db, along with the hashed password, i.e. hash(salt+password)
.
If your database gets compromised and someone gets all the hashes and the salts, they cannot run a rainbow table attack against your hashes - they will need to brute force each hash. With a good hashing algorithm, the brute force attack is unfeasible.
What is a rainbow table attack?
Lets assume a generic hashing algorithm, hash(f)
.
I, as an attacker, precalculate common passwords (f
) and their hashes (hash(f)
). Now, when I get your unsalted database of hashes, I just need to look through your database for hashes that match my precalculated table (rainbow table).
For example, if my rainbow table stores that for f = qwerty
, hash(f) = someRandomHash
, I look through your database for someRandomHash
and as soon as I find it, I know that user's password is qwerty
.
However, if you salted your passwords, when a user set his password as qwerty
, you calculated his hash as hash('saltqwerty
), which means, you did not calculate his hash as someRandomHash
but instead as someRandomSaltedHash
. This renders my rainbow table completely useless.
I am left with no choice but to brute force your table. I know the salt, but I don't know the password, so I have to calculate hash(salt+password)
for every possible permutation and combination of password. With a slow enough hashing algorithm, this can take centuries (worst case).
How do you login a user?
User submit his user_id and password. You query the database for the salt for that user. Then you compute hash(salt+password)
and compare against the hash stored in your database.