Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I always thought that salts is simply used to prevent rainbow tables to be used. Other have suggest they should be unique on a per account basis. Currently i have been using a config file to use as salt. In the past i did md5(salt + password) but now i use .NET PBKDF2 via (pass, salt_from_config).

Have i been doing this wrong or not as securely? Should salts be unique or are they just non predictable so no one can generate a rainbow table ahead of time?

share|improve this question
add comment

3 Answers 3

up vote 13 down vote accepted

I posted an answer that explains this on another question, which should give give you a good background to all the major security concerns around password storage.

To answer your question more directly - a salt:

  • must be unique.
  • should be unpredictable.
  • should be unknown to potential attackers.

The problem with schemes like H(pass + username) is that the attacker knows the salt. So, whilst his ability to crack every password in the database with a single rainbow table is gone, he can create a rainbow table for key user accounts. This allows him to compute the rainbow table for a privileged user account (e.g. admin) ahead-of-time, then immediately use it once he breaches the database.

This is a problem, because it gives you no time to react to the breach. Seconds after you get alerted about the attack, the attacker has logged into your admin account. If the attacker is forced to crack the password after the breach, it gives you time to lock down privileged accounts and change passwords.

You could also look into a salt + pepper scheme, where the pepper is a second salt stored outside the database, e.g. in code. This helps prevent against the SQL injection model of attack, where the bad guy only has access to the database.

Best practice is something like this (feel free to omit the pepper):

hash = KDF(pass + pepper, salt, workFactor)

Where:

  • KDF is a strong, slow key-derivation function, such as bcrypt of PBKDF2.
  • pass is a strong password (enforce password policies!)
  • pepper is a long random constant value stored in your code.
  • salt is a long random unique value stored with the password in the database.
  • workFactor is appropriate for your hardware and security requirements.
share|improve this answer
    
+1, i'm curious, what if i mix the salt and pepper instead of pepper+pass? I'll assume same idea. What if the salt is hardcoded within app and the pepper mixed with salt is the rowid? This solves unique and unknown (hardcoded in app or selected in config file). However i don't understand the unpredictable part. As long as the attacker cant guess the salt its considered unpredictable? hash = KDF(pass, salt ^ userid, workFactor –  acidzombie24 Jul 22 '12 at 21:26
    
Well the userID is predictable if it's an auto-increment. Can you guarantee to never leak a user's ID? The reason for mixing pass + pepper is that the salt for bcrypt is automatically generated, so it's easier to implement. You should not hard-code the salt, since it is an integral part of the security of bcrypt. The same goes for PBKDF2, since it uses HMAC, where the salt becomes the key. It must be unique. The pepper is only there for obfuscation purposes, as an extra defense against the SQL injection model of attackers. –  Polynomial Jul 23 '12 at 6:00
    
ok there is one more thing i am not clear on. Why can't i leak the pepper if the salt is hidden?, How is it an extra defense against SQL when the salt isnt in SQL in the first place? Finally why should i not hard code the salt? (actually i'll have it in a config file but i'm sure you considered that as the same problem) –  acidzombie24 Jul 23 '12 at 8:24
    
The way i see it you cant see the salt if you have SQL access. The pepper being userid will force the attacker to generate more hashes bc salt+pepper is different per user. And because the salt is not known/unpredictable until the user get access to the salt info on the server he cant start the attack ahead of time. –  acidzombie24 Jul 23 '12 at 8:28
2  
Security is about defense in depth. You want to choose approaches that provide overlapping layers of protection. It does not cost you anything extra to generate a random salt on user password creation, so why would you do anything else? Any time you do a good-enough half-measure when it would have been just as easy to do it absolutely correctly, you've failed to provide overlapping security measures. –  Stephen Touset Oct 29 '12 at 16:18
show 8 more comments

Salts should be unique for every password.

If you are using the same salt for every password, an attacker could simply generate a rainbow table using that particular salt and crack most of the passwords in your database.

With regards to the comments about PBKDF2 and GPU acceleration, I would like to point you to this link right here at Security.SE where Thomas Pornin gave a very excellent answer.

share|improve this answer
    
If i am using PBKDF2 wouldnt that take years? –  acidzombie24 Jul 21 '12 at 2:54
    
No. Why would it? Such a task can be done in parallel using GPU clusters. Having the same salt means that only ONE rainbow table needs to be generated, and most of the passwords in your database would be cracked. –  Terry Chia Jul 21 '12 at 2:59
    
hmm, +1. I thought PBKDF2 algorithm can't be done (efficiently?) on GPUs. It appears they can. –  acidzombie24 Jul 21 '12 at 3:16
3  
PBKDF2 usually uses SHA256, which can be done easily on GPUs. Bcrypt and especially Scrypt are much harder to do so, which is exactly why they are recommended. –  Matrix Jul 21 '12 at 6:26
    
PBKDF2 is still pretty good. GPUs accelerate it massively, but your security margin is still greater than your performance hit. Even if the GPU can do SHA256 ten thousand times faster than your CPU, you only have to compute one hash, but the attacker has to compute billions. I agree that bcrypt is better, though. –  Polynomial Jul 21 '12 at 8:11
show 2 more comments

Exact requirements for a salt depend on the password hashing algorithm, but for the usual methods (bcrypt, PBKDF2...) the only requirement is that the salt is unique. Or at least as unique as is practical; the odd collision is not a big issue as long as it does not happen often and cannot be forced from the outside.

Uniqueness is worldwide; it is not sufficient for salts to be unique in a given server. Two distinct servers, using the same hashing algorithm, should have distinct salts too.

A relatively common and cheap way to get worldwide uniqueness is to generate salts from a cryptographically strong PRNG, with sufficient length (16 random bytes are sufficient). That's what bcrypt does. If the PRNG is biased, then you need a somewhat longer salt to achieve uniqueness. If the PRNG is weak because of too small a seed or internal state, then uniqueness will not be satisfactorily obtained that way. The user name is not a good salt, for two reasons:

  • The same user name can occur in several servers (e.g. each server might have an "Administrator" account, under that exact name);
  • The user does not change his name when he changes his password, leading to salt reuse.

Salts are not the same thing than keys (which are secret and must remain confidential) or initialization vectors (IV are "starting points" for some algorithms, and may have additional requirements such as uniformness and unpredictability in the case of CBC encryption). There is normally no problem in giving away your salt values; anyway, whoever recomputes the hash value from the password must know the salt. Therefore, publication of salts is intrinsic with password-based encryption of files (the salt is then encoded in the file header). It is also necessarily published in authentication protocols where the hashing occurs on the client (that's quite rare in Web contexts, because Javascript is too slow). There is no point in needlessly publishing the salts, but keeping them secret does not really enhance security either.

In this answer, a fringe scenario is evoked: an attacker learns the salt beforehand, prepares a big precomputed table, then enacts the actual attack which reveals the password hash. This does not make it easier for the attacker to break the password; in fact, this increases his effort (he has to produce a full table instead of stopping when the password is found, so that's double cost on average; if the table is of the rainbow persuasion, an additional 1.7 factor enters for table generation; and there are storage costs). What it changes is the dynamics: this shortens the time between the break-in (the hash value is stolen) and the password recovery. This is an edge case, so don't sweat it. If you use password hashing for storage in an authentication protocol, where hashing occurs server-side, then you just store the salt with the hash value and the salts will be as confidential as the hash values themselves, and that's good. In other cases (e.g. password-based file encryption), salts will be more "public", but that's not critical in any way, so don't go about adding extra complexity to keep the salts secret (extra complexity is bad, and much worse than public salts).

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.