Given the desire to have unique salts for each user of your system, is it actually necessary to create a cryptographically-random salt for each user? If your system already has some other unique user identifier (be it an ID, user-name, or an EmailAddress) is there any effective decrease in your security if you simply use that value as your salt? It results in a unique salt for each user, and does not require the additional generation and tracking of a new value per user.
The salt in a hash actually forms two different purposes. Generally, it is acceptable for a salt to be known, so let us consider
In the case of 1) anything you add as salt will do, quite literally. The problem is the case of two. The reason for using unique, random salts is that the chances of colliding salts for a specific hash output are vastly reduced. For example, hashing |
|||||||
|
|
Salts must be unique. Randomness (with a "good" random generator) is sufficient to ensure uniqueness. A per-user ID (e.g. the user login name) is not sufficient for uniqueness, because it does not capture some occurrences which do happen in practice:
Even if these two specific cases happen not to be a worry in your situation, you cannot be sure that you thought of all possible cases. On the other hand, a random salt, of sufficient length (say 128 bits or more) and filled with appropriately good random bits (from a cryptographically secure generator), provably yields the uniqueness you need (with overwhelming probability). |
|||||||||||||||
|
|
The real purpose of the salt is to make it so that the attacker can't even start to use their resources to brute force until they know the salt, therefore buying valuable time to change passwords after a breach. If the salts generated in any predictable manner, an attacker already has a head start on breaking your passwords - they can do all the computational work (in the form of rainbow tables for the salts they are interested in) in advance of actually breaching the system to get the password hashes. Keep salts random, keep them long, keep them secret, and keep them individualized per-hash. You can add a global hash to that as an additional hash, but it should also be long and random, and you should have it planned in advance how to handle changing it often. |
|||
|
|
|
The purpose of a salt is to make it difficult to precompute the inverse hash table, and to prevent the birthday weakness. Neither of these require the salt be random, just unique. For a real life example, by default Kerberos uses your username and realm as the salt. Given the nature of Kerberos it absolutely must be predictable for a given user. But since username+realm is unique, you cannot precompute a rainbow table once and use it against every site in the world. Even in the weaker configuration using realm-only salts, you'd have to recompute it for every domain you wished to attack. |
|||
|
|