12

Using PHP, I am encoding passwords using the hmac function with the sha256 algorithm. What I'm not sure about is how to properly store the salt.

The whole point of hashing a password is in case a hacker gets access to the database. If I store the salt in the db within the same row as the hashed password, isn't it just like I am handing the hacker the "secret code"? I am putting up a door with a lock, and handing the intruder the key.

Can anyone please explain to me how they come about storing their salt?

Michael Berkowski
  • 267,341
  • 46
  • 444
  • 390
steeped
  • 2,613
  • 5
  • 27
  • 43
  • duplicate: http://stackoverflow.com/questions/1219899/where-do-you-store-your-salt-strings – Janus Troelsen Mar 27 '12 at 21:22
  • Unless I'm wrong the salt is unique to each row therefore no...you are no giving them a secret code just part of the recipe – David Nguyen Mar 27 '12 at 21:23
  • 2
    The point of a salt is not to be secret; it's to prevent an attacker from amortizing the cost of a brute force / dictionary attack across many accounts or many servers. – Michael Borgwardt Mar 27 '12 at 21:24

3 Answers3

16

Putting the salt into the hands of an attacker who has stolen your database isn't actually a problem. Combining the salt with the original password into the password hash protects against the attacker using "rainbow tables" of millions of known and well-known password hashes to obtain the passwords of some of the stolen user ids.

Having hashed the password and salt together makes it many orders of magnitude more difficult to crack even a single password, on the basis that the salt invalidates the password hashes known in the rainbow table. So even if the salt is known by the attacker for each of your users, this means that in order to crack any single user, the attacker must compute a whole new rainbow table just for that user alone, which combines the user's salt with the rest of the passwords known in the rainbow table they started with.

Salting the password does not make it impossible to crack a password, but far more difficult. An attacker could, for example, target a small subset of your users with the hash and salt in hand, and that's another reason to encourage strong passwords which are less likely to appear in a rainbow table.

Michael Berkowski
  • 267,341
  • 46
  • 444
  • 390
  • Also to note, good thread talking through some other points http://security.stackexchange.com/questions/3272/password-hashing-add-salt-pepper-or-is-salt-enough – Ryan Gibbons Mar 27 '12 at 21:27
  • 3
    +1 I would just add that you can further hinder an attacker by adding an application-wide salt that's stored somewhere other than the database. That way even if someone gets a hold of the DB, they will still be missing a key piece of information. – NullUserException Mar 27 '12 at 21:27
  • Also: If you DO store salt somewhere else, the attacker may even have to grab the last option - bruteforce, since he wouldn't be able to compute a rainbow table. EDIT: ^Already written – JanLikar Mar 27 '12 at 21:32
  • @JanL Bruteforce would (should) be extremely impractical. Without access to all salts, the hashes are rendered useless. They would then be forced just to attack the login page/script itself, and you *should* have a rate limit (eg: after 5 failed attempts, block the account or ask for a CAPTCHA) – NullUserException Mar 27 '12 at 21:41
  • @NullUserException The problem with that is IP spoofing. If you're going to ask for a CAPTCHA, then always ask for one. Unless you're keeping track of how many times somebody has been trying to log into somebody's account rather than how many times an IP address has tried to log in to an account. – Andrew Mar 05 '13 at 18:37
  • 1
    @Andrew It's impossible to spoof an IP due to the 3-way TCP handshake. Always asking for a CAPTCHA inconveniences legitimate users. – NullUserException Mar 05 '13 at 22:49
3

I would opt for storing salt along with hashing algorithm's identifier and the hash itself.

Here is why:

Usually the the access to database is limited to localhost or some predefined range of IP addresses. Which means that, for a hacker to gain access to your database, he/she would need to compromise your servers filesystem (either by gaining direct access or injecting a script). Or perform an SQL injection.

In the former case it would mean, that if someone gained access to your salts in DB, he/she could as easily read them from your PHP files source.

The latter cause can be simply prevented by use of prepared statements with either PDO or MySQLi. You shouldn't be using the old mysql_* functions as API anymore. They are not maintained anymore and the process of deprecation has begun already.

Even if someone gets his/her hands on your DB, it is not all that problematic. If you are using crypt() function for creating hashes with good algorithms (recommended would be CRYPT_BLOWFISH), then cracking even a single password can be exceedingly long (in the scale of years). By that time you can easily send out "change your password" notifications to users, and lock all the ones, who have not done so.

If you are using PHP 5.5+, you should instead be using the new password API: http://php.net/password

tereško
  • 58,060
  • 25
  • 98
  • 150
2

The salt is intended to be as cleartext and immediately available. A password hash is perfectly non-reversible, but it is dictionary attackable. As such, salt enough to add a few orders of magnitude to perturb the dictionary attack. Making the salt available should not degrade the security of the hashed password.

Jé Queue
  • 10,359
  • 13
  • 53
  • 61
  • 2
    Aren't "perfectly non-reversible" and "dictionary attackable" totally contradictory? Perfectly non-reversible would imply that you can't possibly get the original plaintext password, which is obviously not the case. – NullUserException Mar 27 '12 at 21:24
  • 1
    Nope, you can INFER the original password via a dictionary/rainbow table. You still can't reverse the hash. Additionally, it is a possibility that multiple inputs digests to a single hash output. – Jé Queue Mar 27 '12 at 21:27
  • From the point of view of someone who just got their password cracked, what's the difference? – NullUserException Mar 27 '12 at 21:29
  • 1
    Users will always be mad, but putting the salt adjacent to the hash or keeping it separate will not change that liability. – Jé Queue Mar 27 '12 at 21:32
  • No, I meant: for someone whose password got cracked, what's the difference between "reversed" and "inferred"? – NullUserException Mar 27 '12 at 21:34