Search code examples
phpsecuritysalt-cryptographycryptpassword-hash

How to get salt from a password and use it to validate user?


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:

  1. User enters a password
  2. Random create a salt
  3. Hash password and salt
  4. Store result in database

But then how do I recover the salt when user tries to login?

  1. User enters his password
  2. I somehow add his own unique randomly generated salt
  3. Hash both of them together
  4. Compare it to hashed salted password stored in Database.

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?


Solution

  • 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.