21

Ever since I've been making sites that require a user to log in with a username and password I've always kept the passwords somewhat secure by storing them in my database hashed with a salt phrase. Well just recently I read it is bad practice to use a single static salt word. Instead you should use a random salt for each user.

I under stand generating a random salt word for each user. But my question is, if you have to store the random salt also in your database so you can use it to cross reference it later to check the users inputted password when they log in. Doesn't that make it just as easy if usernames and passwords are stolen from your database then wouldn't they have just as much access to the random salt values as well? Seems like that extra layer of security doesn't really add much to the equation.

Or am I going about this all wrong?

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
Ryan
  • 401
  • 3
  • 7
  • 6
    The reason I down-voted the answer with "they wouldnt know the method of encryption" (now deleted, so I can't comment) is [Kerckhoffs's principle](http://en.wikipedia.org/wiki/Kerckhoffs%27s_principle). The enemy knows the system. *Don't* assume any of the system (which hash algorithm, iteration count, etc.) is secret. Only the actual password is a secret. – Matthew Flaschen Jun 20 '12 at 21:59
  • I think this is a great question. I've learned a great amount of knowledge from the answers of this question, especially @Matthew Flaschen's answer. I think you should undo your flag. –  Jun 20 '12 at 22:05
  • I thought I read this comment earlier but it must have been deleted because I don't see it now. But I guess if my entire database is compromised then it wouldn't matter so much because potentially all the rest of the users information is now accessible anyways and the password wouldn't matter except for keeping it secret from the public in case of it being used multiple times on other sites. –  Jun 20 '12 at 22:15
  • 1
    @Ryan, even setting aside other sites, it's not just about confidentiality/privacy. If I steal only PayPal's database (assume it's plaintext, but passwords are salted and hashed), I know users' addresses and transaction histories. But if I know a user's password, I can do additional transactions. – Matthew Flaschen Jun 20 '12 at 22:27

5 Answers5

18

It does add one significant thing. If they steal the database, they have the username, per-user random salt, and hashed password. But they still don't have the original password. To reverse the hash, they will generally have to do a significant amount of separate work for each user.

Without any salt (a very bad idea, as LinkedIn learned), attackers can use pre-existing rainbow tables and have no per-user work for hashes that benefit from the tables. Even if no part of the hash is in the table, they can pool work (e.g. if a user has two accounts with the same obscure password).

With a per-site salt, they can generate a rainbow table for the site, and still share work between users.

Remember that if they do crack a user's password, besides being able to log in to your site, they can probably also log in to other sites the user uses.

  • One-way functions are pretty good with salt. Especially if the hackers don't know what function you used. –  Jun 20 '12 at 21:56
  • 5
    @TheZ, like I said above, you should assume the attacker knows the function. [Kerckhoffs's principle](http://en.wikipedia.org/wiki/Kerckhoffs%27s_principle). – Matthew Flaschen Jun 20 '12 at 22:00
  • 5
    TheZ: It's usually fairly easy to tell what function was used based on the length. The function should never be considered a part of your security, as keeping that a secret only equates to a security through obscurity measure. I would assume if the DB server is compromised, it's possible the app server can be compromised, at which point your app can be decompiled and the function becomes obvious. –  Jun 20 '12 at 22:01
  • 3
    @Ryan it does not matter, salts are not supposed to be secret, if helps if they are, but the what they are supposed to be used for is not allowing precomputed tables or re-using past work. See my comment on hsanders answer. – Scott Chamberlain Jun 20 '12 at 22:36
9

What it does for you is it forces them to generate a rainbow table per user instead of a rainbow table for the whole site to crack your password. It also means they can't just google your hash values, which is the "ultimate rainbow table". It changes the cracking proposition to a much more difficult task.

Google "5f4dcc3b5aa765d61d8327deb882cf99". See what you get (hint it's the MD5 hash of password, and there are thousands of results).

Hashing every passphrase with a different salt is better than using one salt, but one salt is better than no salt at all.

hsanders
  • 191
  • 1
  • 4
  • 5
    I want to emphasize this point. Salts are not supposed to be kept secret, what they are supposed to be used for is to prevent a precomputation attack, so a attacker can do the work ahead of time (or reuse existing work) to crack the password. Adding one salt for the database helps protect you from them precomputing rainbow tables, however once they find out that the hash of "Password1" is 0xDEADBEEF they can check the entire database and anywhere they see 0xDEADBEEF they know that users password. If you use a salt per user "Password1" would be 0xDEADBEEF on one user and 0x12345678 for another. – Scott Chamberlain Jun 20 '12 at 22:34
3

The salt is for making the password processing different for each user. Otherwise, the attacker who got a copy of your database (you store password hashes precisely because you envision this situation) could optimize his search and attack all the passwords with the same effort than what it takes to break a single password (rainbow tables, like any other precomputed tables, are an incarnation of this concept). With per-user salts, at least, the attacker will pay the full brute-force effort for each password he wants to crack.

(Ideally, you use a per-user salt that you also change whenever the user changes his password. So it really is a per-password salt.)

Salts are only half of the story; you also want the hashing mechanism to be slow (in a configurable way, but very slow nonetheless). A simple hash is too fast, attackers can literally compute billions of them per second.

Use bcrypt. Bcrypt implementations handle the salt generation and usage, and bcrypt can be made as slow as required.

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • I still don't get it. Any salt prevents the use of rainbow tables, so what difference does it make if the salt is unique to each username? – Celeritas Jan 04 '17 at 12:02
  • 1
    @Celeritas The only salts that actually prevent use of tables (rainbow or not) are salts that are unique to each hashed password instance (so at least unique for each user). If you have a "system wide salt" then it prevents application of tables downloaded from somewhere else, but an attacker can still build his own tables for _your_ system salt and apply them on the thousands of hashed passwords of all the users on your system. – Thomas Pornin Jan 04 '17 at 19:33
2

Individually salting passwords helps to prevent attacks leveraging an off-line pre-computation step, such as time-memory tradeoffs (raibow tables). This forces the attacker to brute-force the hashes for recoverin a password. This blog post details several password storage strategies, from the least secure to the most secure one.

cryptopathe
  • 185
  • 4
1

Let me add that you don't want to hash with MD5 or SHA-1. Those were designed to be fast-hashing. Which is the exact opposite of what you want when someone is trying to crack your password list. Hash with bcrypt, that is designed to be slow. This is an option many developers overlook.

Edit: Here's a good article about it.

Edit: Another article says PBKDF2 and scrypt are also good choices.

  • 1
    Whatever algorithm someone chooses, they should use salt. Preferably on a per user basis. It makes every cracking proposition that much harder. –  Jun 20 '12 at 22:12
  • 1
    yep I read that today as well. I had been using sha1 but from now on I'll be sure to use sah256 or 512 or possibly one of the slow hash functions. –  Jun 20 '12 at 22:13
  • 1
    @hsanders - Agreed. From now on, my auth systems will all use bcrypt-hashed passwords with random salts. –  Jun 20 '12 at 22:20
  • bcrypt is a good tool to consider. However, like many articles telling everyone they're wrong, it overstates the case. "It doesn’t affect how fast an attacker can try a candidate password, given the hash and the salt from your database." is true. "Salts Will Not Help You" is completely false. That's why at the end they have to admit, "bcrypt has salts built-in to prevent rainbow table attacks" But he then absurdly claims "I’m not saying salts are without purpose" (remember, this is the same guy who said "Salts Will Not Help You"). Salts **do help**. They're just not the be-all end-all. – Matthew Flaschen Jun 20 '12 at 22:23
  • @MatthewFlaschen - Agreed. I linked to him not because I agree with his stance on salts, but because of the info about MD5/SHA1 vs bcrypt. –  Jun 20 '12 at 22:26