133

Any salt at all will obviously help when salting and hashing a user's password. Are there any best practices for how long the salt should be? I'll be storing the salt in my user table, so I would like the best tradeoff between storage size and security. Is a random 10 character salt enough? Or do I need something longer?

Shervin Asgari
  • 22,044
  • 28
  • 92
  • 138
David
  • 6,877
  • 6
  • 29
  • 25
  • 1
    Or if there is optimal ratio for the length of salt to the length of hash output? 8-byte salt might be enough for HMAC-SHA-256, but may not to HMAC-SHA-512. – Crend King Feb 23 '11 at 02:16
  • 2
    For those who don't know what salt is: Salt (cryptography) on Wikipedia – David Koelle Oct 08 '08 at 18:49
  • 10
    I don't have a recommendation about the length of the salt, but the answers that are showing up here have a lot of bad information. Your salt should definitely: - be random - be per secret (not a single value stored in your program image or configuration file). The salt is not a cryptographic secret, so storing it in your table is no problem. The only purpose of a salt is to ensure that when different instances of the same item are hashed (or encrypted) that you get a different result. – Michael Burr Oct 08 '08 at 18:44
  • 1
    Cryptographically random salt the same size as the output of the hashing function means that a "try all possible salts" (plus a password dictionary) attack requires as much effort as a "try all possible hash results" attack - which is a standard brute force. A shorter salt means that you can have a salt dictionary plus a password dictionary as a brute force attack. – Richard Gadsden Jul 07 '11 at 15:16
  • -1 Admittedly does not (even attempt to) answer the question. – user359996 Aug 30 '11 at 22:56

5 Answers5

73

Most of these answers are a bit misguided and demonstrate a confusion between salts and cryptographic keys. The purpose of including salts is to modify the function used to hash each user's password so that each stored password hash will have to be attacked individually. The only security requirement is that they are unique per user, there is no benefit in them being unpredictable or difficult to guess.

Salts only need to be long enough so that each user's salt will be unique. Random 64-bit salts are very unlikely to ever repeat even with a billion registered users, so this should be fine. A singly repeated salt is a relatively minor security concern, it allows an attacker to search two accounts at once but in the aggregate won't speed up the search much on the whole database. Even 32-bit salts are acceptable for most purposes, it will in the worst case speed an attacker's search by about 58%. The cost of increasing salts beyond 64 bits isn't high but there is no security reason to do so.

There is some benefit to also using a site-wide salt on top of the per-user salt, this will prevent possible collisions with password hashes stored at other sites, and prevent the use of general-purpose rainbow tables, although even 32 bits of salt is enough to make rainbow tables an impractical attack.

Even simpler-and developers always overlook this-if you have unique user IDs or login names, those serve perfectly fine as a salt. If you do this, you should add a site-wide salt to ensure you don't overlap with users of another system who had the same bright idea.

SecurityJoe
  • 1,065
  • 9
  • 5
  • 19
    There is a benefit in salts being unpredictable. A predictable salt could be predicted and used in a hash table attack. For instance, if your salt is just the userID, then a plain alpha hash table that's long enough will include not just all passwords, but all username + password combinations. – Richard Gadsden Jul 07 '11 at 15:10
  • 7
    Note in relation to your last paragraph, if you use a site-wide salt, that should be exactly that: site-wide. Not application-wide, ie each new instance you install of your application should generate a new site-wide salt. For instance, if Windows used the same salt on every Windows authentication database, then it would be worthwhile to create a rainbow table for that salt, but if every install of Windows generated a new salt, then it wouldn't. – Richard Gadsden Jul 07 '11 at 16:04
  • 5
    The issue isn't really that the salt needs to be hard to guess. The attacker doesn't need to guess the salt: anyone who has access to the hash already has the salt. The issue is that if your salts are very common (like usernames), they might be the same as those at other sites, and at that point the attacker needs a much smaller set of rainbow tables to make attacks feasible. This is why the per-site salt idea is mentioned, to avoid this kind of collision with other sites. – Nate C-K Jan 24 '14 at 02:26
  • 3
    Quick note: If using usernames as the salt, this can be an issue if usernames change. Practically, (despite what is said in the customer's design documents) I've found that users often want to change usernames. – SilentSteel Jul 21 '14 at 20:38
  • 6
    @NateC-K, The per-site salt idea you are talking about is called pepper. – Pacerier Dec 10 '14 at 04:24
36

Currently accepted standards for hashing passwords create a new 16 character long salt for every password and store the salt with the password hash.

Of course proper cryptographic care to create really random salt should be taken.

Chris Ballance
  • 32,056
  • 25
  • 101
  • 147
David Schmitt
  • 54,766
  • 26
  • 117
  • 159
25

Edit: My below answer answers the question as asked, but the "real" answer is: just use bcrypt, scrypt, or Argon2. If you're asking questions like this, you're almost certainly using tools at too low a level.

Honestly, there's no defensible reason not to have the salt be the same exact length as the hashed password. If you're using SHA-256, then you have a 256-bit hash. There's no reason not to use a 256-bit salt.

More than 256 bits won't net you any improvement in security, mathematically. But going with a shorter salt may always end up with a situation where a rainbow table catches up to your salt length -- especially with shorter salts.

Stephen Touset
  • 2,404
  • 2
  • 24
  • 24
  • What do you mean by 'More than 256 bits won't net you any improvement in security'. My belief was that salt defended against – mrmcgreg Mar 03 '11 at 15:57
  • 15
    Salts defend against rainbow tables. A 512-bit salt with a 256-bit hash will still only result in 256 bits of entropy in the final password. – Stephen Touset Mar 15 '11 at 19:45
  • 1
    @Stephen I beg to differ. Entropy is not the issue here. Let's say we have a 3-bit hash, you are saying having 3-bit salt on a 3-bit hash is as secure as having a 9999-bit salt on a 3-bit hash. This is incorrect, an attacker can simply have a pre-generated full set of rainbow tables for all combinations of your 3-bit salt + 3-bit hash, achieving O(1) time needed to crack each row even when each secret had its own salt.... – Pacerier Jul 06 '12 at 06:42
  • ...However, if your salt is 9999-bit long, it is unlikely that there is already a pre-generated rainbow table for that 9999-bit salt. Hence the time needed to crack each row would take O(m) where *m* is the cost of performing a hash. – Pacerier Jul 06 '12 at 06:44
  • 7
    If you have a 3-bit hash, your 9999-bit salt will still only hash down to 3 possible bits of entropy. A rainbow table would only have to find three salts for each password that result in a different output, which is a constant multiplicative factor and thus discarded from the big-O. – Stephen Touset Jul 06 '12 at 14:51
  • 1
    To clarify, I don't have to store a rainbow table with 2 ^ 9,999 salts. Just eight (three bits worth) entries for each password in the rainbow table. Again, you have gained nothing. – Stephen Touset Jul 06 '12 at 15:03
  • Also note that solving for those three bits is exactly equivalent to brute-forcing the entire hash output space. – Stephen Touset Jul 06 '12 at 15:10
  • 1
    Remember that the longer your salt and hash algorithm, the bigger the performance hit your site will take – John Czajka Feb 03 '11 at 20:43
  • 11
    That's not *that* big a deal; the user will barely notice the difference between a millisecond hash and a half second hash, plus password hashing actually *should* take longer to slow down brute force attacks -- although typical three strikes locked out for 15 minutes is better. Are you "wasting" CPU cycles to do this? Yeah, whatever. The CPU spends more time idle than not on most websites anyway, so what does it matter? If you're running into performance issues, scale out. – Randolpho Feb 03 '11 at 21:21
  • 10
    [Slow hashing](http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html) is a feature, not a bug. – outis Sep 15 '11 at 22:43
  • @Pacerier if you're on a budget you probably shouldn't be storing credentials at all -- look into OpenID, or Google or Facebook login. – Randolpho Jul 06 '12 at 15:07
  • @Randolpho Everyone is on a budget, and OpenID has its disadvantages: http://www.quora.com/OpenID/What-s-wrong-with-OpenID – Pacerier Jul 07 '12 at 09:46
  • 1
    I love how the default login option for the link you provided is Facebook and Twitter login. – Randolpho Jul 07 '12 at 22:22
  • @Randolpho Facebook isn't OpenID btw. – Pacerier Jul 09 '12 at 19:28
  • No, it's a custom flavor of OAuth. But I'm pretty sure I wrote "look into OpenID, or Google or Facebook login". OpenID isn't the only game in town. – Randolpho Jul 09 '12 at 19:44
  • @JohnCzajka while true the sentence can be turned around, long salts means more cpu time to crack it. – Peter Jul 11 '13 at 09:18
  • @Randolpho, I'm pretty sure I wrote "Facebook isn't OpenID". Also, do read that link. – Pacerier Dec 10 '14 at 05:03
  • @StephenTouset, The 9999-bit salt will still only hash down to 3 possible bits of entropy, but let me repeat: **entropy is not the issue here**. It doesn't matter if you can login as the user in that ................................. ..................................................................................... – Pacerier Dec 10 '14 at 05:03
  • 2
    ...................................................................................... particular system. [The **purpose of salts** is to stop precomputation attacks so that hashes cannot be searched for and immediately reversed into plaintext](http://goo.gl/4GudMb) . With a 9999-bit salt, **your password remains a secret**, whereas with a 3-bit salt, your password is now known to the whole world (and they can use it to login to your other accounts since many people often reuse passwords). I find it amusing that 5 folks here had actually upvoted your comment due to the word "entropy" in it. – Pacerier Dec 10 '14 at 05:09
  • Salts are not considered private. If your table of password hashes leaks, then almost certainly your salts have leaked as well. – Stephen Touset Sep 27 '16 at 18:23
7

Wikipedia:

The SHA2-crypt and bcrypt methods—used in Linux, BSD Unixes, and Solaris—have salts of 128 bits. These larger salt values make precomputation attacks for almost any length of password infeasible against these systems for the foreseeable future.

128-bit (16-byte) salt will be enough. You can represent it as a sequence of 128 / 4 = 32 hexadecimal digits.

tellnobody
  • 8,201
  • 3
  • 29
  • 28
2

One answer might be to use as size of salt the value that the hash you are going to use provides in term of security.

E.g. If you are going to use SHA-512 use 256 bit salt since the security provided by SHA-512 is 256 bit.

Roberto Martelloni
  • 527
  • 1
  • 5
  • 16