15

Since I'm hashing all passwords with each their own salt, is there a benefit to the salt being really random, or would an incremental counter or a guid be good enough? Also, is there a benefit of having a bigger salt vs. a smaller salt?

EDIT: Since it is established that hashes shouldn't be too small: What is a sufficient size of a salt? Will a guid (16 bytes) do?

Andrei Botalov
  • 5,267
  • 10
  • 45
  • 73
Arjan Einbu
  • 342
  • 4
  • 13

3 Answers3

19

The unique purpose of the salt is to be unique: no two hashed passwords shall use the same salt value. This is meant to prevent cost sharing such as precomputed hash tables.

Uniqueness should be worldwide. For instance, suppose that you used a simple counter as a salt. Correspondingly, the value "1" will be used as salt for the first created account, presumably the one for the server administrator. This will be true for all installed instances of that server. This makes it worthwhile to precompute a big table (e.g. a rainbow table) of potential hashed passwords using "1" as salt, because that table could be used to attack the administrator password on all servers which use that software. The word to meditate here is "worthwhile".

Since server-wide uniqueness is not enough, a counter will not be sufficient; the user name is not a good salt either (user names are unique on a given server, but there are many 'Bob', 'Joe' and 'DarkLord42' out there). An UUID (GUID) is supposed to do the trick. You can also use a strong uniform pseudorandom generator (/dev/urandom, CryptGenRandom(), java.security.SecureRandom... depending on the platform you use) and get enough random bytes from it so that risks of reusing a salt value are sufficiently small; 16 bytes are enough for that. Using randomness is the "robust way" because it yields uniqueness with a sufficiently high probability, without having to rely on world-wide conventions.

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • in that respect a linear congruential number generator with a long enough period (over 128 bits) with seed and the `a` and `c` parameters initialized to some (secure) random value would be ideal – ratchet freak Oct 19 '11 at 17:40
  • 2
    @ratchet: even simpler: use a 128-bit counter with a random starting point. This still ensures the same low risks of collisions. But maintaining a counter may be more expensive than using randomness (the counter value must be saved and kept across reboots, which can be a cumbersome requirement). – Thomas Pornin Oct 19 '11 at 18:03
8

Thanks to Hendrik's comment to the question, I found a thread related to this. Here are my findings:

  • Using an incremental counter as a salt will still make it harder to use rainbow tables.
  • Bigger is generally better, and randomness is preferred to avoid reuse.

If everyone (or at least several) used the same set of salts (ie. incrementing numbers or short salts), a rainbow table could be created for all of the repeated salts, making those salted hashes less secure.

So the salt should preferably also be unique across systems and not only within my system to avoid a set of rainbow tables to be created and used to compromise several systems. (One table for salt=1, one for salt=2, one for salt=3 and so on.)

Arjan Einbu
  • 342
  • 4
  • 13
0

A salt is not required to be random nor secret. It is only meant to halt attacks using e.g. rainbow tables, or make such attack much slower. If I'm not mistaken it should be safe to salt a users password with his/hers username.

efr4k
  • 497
  • 3
  • 13
  • 10
    Thanks! That was my first thought too, but my later findings say you could then create rainbow tables for common usernames like "admin" or "root". Randomness seems to be a key... – Arjan Einbu Oct 19 '11 at 12:23