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.