27

I recently had a comment made to me in an online discussion after I'd stated that randomness in a salt doesn't matter -- and I got the following response:

Salts may not have to be "secure," but the method of generation can matter. Using a cryptographic random data source helps ensure uniqueness and randomness in the salt data. Depending on the algorithm being used, the distribution of randomness in the salt can have bearing on the strength of the key.

Now, in most cases with a 22 character salt (in bcrypt for example) even with a prng the odds of generating the same salt twice are pretty small but its the second bit of that statement -- I'm not sure what that means and I certainly can't say its "wrong" without understanding it ....

So is this correct? Does randomness in a salt matter? Since salts are a known thing if someone's attacking a table of hashes, how can the quality of the salt matter?

curiousguy
  • 5,028
  • 3
  • 25
  • 27
erik
  • 271
  • 3
  • 3

5 Answers5

28

No. A salt is simply supposed to be unique so that you can't use an attack (such as rainbow tables) that computes a password hash once and uses that result against multiple password hashes.

If you're interested in making reversing the hash impossible without some secret knowledge, then append a site-specific password to the provided password (in addition to the salt) before hashing. A salt is stored with the hash, so making it hard-to-guess is pointless.

@Honoki:
If it's a global value or site-specific, then what you're thinking of isn't a salt, it's something else. That's not to say it's not a good idea, but it's not a salt. Typically an installation-specific secret is called a "site key" or "site password".

But salts are typically stored with the hash. For example, here's the current way Unix/Linux login passwords are stored. The password here is "foobar":

$5$BcjmguyyH.Qrf$ADRXhi/5xb.dYU67I.JdY57uoFjel/rqMqj14QJmTQ1
  • $ is the field delimiter
  • 5 is the hash algorithm specifier (in this case SHA-256)
  • BcjmguyyH.Qrf is the salt (not disguised in any way)
  • ADRXhi/5xb.dYU67I.JdY57uoFjel/rqMqj14QJmTQ1 is the hash
tylerl
  • 82,225
  • 25
  • 148
  • 226
  • tylerl: that was always my understanding, thats why I was confused by the posters statement about "the randomness of the salt ..." – erik Jun 16 '12 at 22:52
  • Does the salt have to be appended with the password for it to be a salt? Most salts are stored in that manner, but i could see the salt being stored in another database and referenced when needed working well. In that case, the attacker has to compromise yet another database table to successfully crack the password, which might add another layer of security. At the very least, it will provide a form of security by obscurity. –  Jun 17 '12 at 09:46
  • @TerryChia A salt is just a little bit of randomness added to make sure you never get the same output twice. Hiding the salt isn't a *bad* idea, secrecy isn't the goal that salts are designed to achieve, so by doing so you're really combining two effects (a salt AND a site key) into a single element. I'm of the mind that your salt should be *just* a salt, and you should add a site key separately to get that benefit. But that's just my opinion. It helps to keep the components separate in my opinion. – tylerl Jun 17 '12 at 19:43
  • Salts are not just about rainbow tables, but about general multi-target attacks. For example a per-site instead of per-user salt makes rainbow tables useless, but still allows powerful multi-target attacks. – CodesInChaos Jan 03 '13 at 20:50
  • @CodesInChaos agreed. Updated to reflect the more general usefulness of salts. – tylerl Jan 03 '13 at 21:39
  • From your answer I'm deducing that using DB generated userIds as salt is fine since they are unique... but of course not particularly hidden. They tend to leak into the front-end but that doesn't defeat the purpose of the salt... does it? – Daren Sep 22 '15 at 16:55
9

Given that the point of a salt is to prevent an attacker from precomputing hashes, I'd say it's mostly the uniqueness of the salt that matters, but randomness could be a factor for a particularly resourceful attacker - if your salts are very predictable, it's conceivable that an attacker could generate rainbow tables in advance of an intrusion attempt so as to speed up cracking passwords once they get the hashes.

Some techniques are little better than unsalted passwords - using a single salt for the entire password database means they only have to compute one set of hashes to crack the entire database, and using salts that are predictably derived from usernames (or are the actual username) means that an attacker can precompute hashes for user accounts they are interested in cracking (probably your admin accounts, privileged employees, moderator accounts, etc) even before they get a copy of the database.

In summary the salts need to be unique, and they need to be unpredictable for best security. Cryptographic standards of randomness probably aren't necessary, although they are a good way to guarantee unpredictability.

Stephanie
  • 543
  • 3
  • 10
  • From your first paragraph, how likely is it for an attacker to pre-generate salts if it was randomly generated using a decent enough PRNG? What are the odds of that actually working? I don't see it as being very likely. I feel that a random salt that cannot be deduced from the username would work well enough. Randomness is not a really important factor. –  Jun 17 '12 at 09:49
  • @TerryChia A decent PRNG shouldn't be a problem. A very poor one is at worst entirely predictable based on some externally discernible factor, in which case the attacker can get a head start. – Stephanie Jun 18 '12 at 12:32
  • Thank you, I just started working with a team that uses userIds as salts with the argument that they just need to be unique and felt something was wrong (from reading OWASP) but was lacking arguments. They might be considered too weak but I least I can offer a reason beyond "I read it should be so". – Daren Sep 22 '15 at 16:58
4

Salts don't need to be unique. It's not an absolute requirement. However, the more different salts you use the greater the security so if they can be nearly unique that is good but don't worry about some people potentially sharing a salt due to poor randomisation.

Salt is used to prevent people using a pre-prepared rainbow table to crack your passwords. If you use the same salt on every password, you have foiled the pre-prepared rainbow table but it may be worth the cracker's time to create a custom rainbow table for your salted passwords. If you change the salt for some users, then you reduce the potential gain for the cracker in producing his rainbow table. For example, if you have two salts used randomly, then the cracker needs to create two rainbow tables. If you use 50 salts randomly, then the cracker needs to create 50 rainbow tables - getting more work. If you use a randomly generated salt for each user, the the cracker has to recreate a new rainbow table for each and every user. This is now so much work that the cracker won't bother trying and will use a different attack instead.

If you have randomly generated salts for every user, there is the possibility that two or more user's salts would be identical. This would only marginally affect the sites security. A cracker could now use a custom rainbow table to crack all the identical salted passwords. This might be a viable attack if the number of users with identical salts is large enough. If the number of identical salts is in the single figures, then it would not pose a big issue.

The value of the salt need not be a secret. Hiding the salt value is done by some people but mainstream password systems generally don't. Keeping the salt secret doesn't provide much additional security. The purpose of the salt is to ensure the password algorithms are not similar for each user and so block rainbow table attacks. Knowing the salt doesn't make the hashes any easier to crack so long as the salts are generally nearly unique.

Rincewind42
  • 455
  • 1
  • 5
  • 12
  • 1
    "but it may be worth the cracker's time to create a custom rainbow table for your salted passwords" No it's certainly not since direct multi-target attack against all hashes in the db is more efficient. Rainbow tables are useful if you don't have all hashes you want to crack at the same time or if you need to pre-compute but if you have a full database dump with a per-site salt, there is no reason to create a rainbow table. – CodesInChaos Jan 03 '13 at 20:55
2

In most password hashing schemes, salts must be globally unique. This means that, ideally, every single password instance in the whole world should have its own salt value, shared with none other (in particular, the same salt value should not be used in two distinct servers, and the salt must also be changed when a user changes his password).

Global, worldwide uniqueness is hard, because there is no central repository for allocated salts. An easy way is to rely on randomness: if you generate your salts from a cryptographically strong random generator (i.e. a "very good" generator) and if you make your salts long enough, then probability of a salt collision is very low -- sufficiently low to be neglected. Note that even if we aim at global uniqueness, the occasional collision is not immediately fatal, so we can live with that risk. 16 bytes is "long enough".

Any method which reliably ensures global uniqueness is good; but randomness is often the one which scales best, because it is purely local (no network-wide bottleneck).

Mutatis mutandi, this is the same issue than for UUID. "Version 4" UUID actually 122 random bits. Such UUID would be quite appropriate salts.

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • Since you mention UUIDs, version 1 or 2 UUIDs would also be suitable for salts, if implemented correctly (unique MAC address, and timestamps that do increment), because the UUID doesn't need to be unpredictable. However they would have no advantage over a random salt except on a device with no reliable entropy source. – Gilles 'SO- stop being evil' Mar 20 '14 at 13:48
  • UUID can be more convenient in some programming frameworks: even when the system has a reliably strong PRNG, accessing it from within some software system may be harder than obtaining an UUID. Also, some systems may insist on a slow "initial seeding" process for strong PRNG, which would be useless for a seed. Basically, for a seed, we need something better than rand()-seeded-with-current-time, but not necessarily cryptographically strong, and UUID fit that niche nicely. – Thomas Pornin Mar 20 '14 at 16:11
-1

It clearly matters a bit that salts are random, because at the other extreme if salts were entirely non-random then they would be useless. If everyone just used the word “salt” as their salt, then rainbow tables would incorporate that and it would add no extra protection.

Mike Scott
  • 10,118
  • 1
  • 27
  • 35
  • There is a big difference between "non-random" and "a reused string". – schroeder Jun 08 '21 at 07:38
  • @schroeder Even if there were only two different values, and some people used one and some people used the other, that would be a _very small amount_ of randomness. – Mike Scott Jun 08 '21 at 08:42
  • 1
    As mentioned in previous answers, uniqueness is what matters. A salt initialized at a random value (even with the 32 entropy bits rand() function), then incremented at each new password creation or modification is enough to defeat attacks. Notice that in this scheme, none of the salts are random except for the first one. – A. Hersean Jun 08 '21 at 08:50
  • @MikeScott you are compounding your logic error, not resolving it. – schroeder Jun 08 '21 at 09:25