Given a database where we have usernames and passwords, we want to secure users' passwords by hashing them. We should not use only username and passwords in this hash, as someone having data from other sites that uses the same hashing function can come to the same results and thus know our passwords. If we try hashing the passwords by themselves it would be easy to bruteforce the entire database and guess all the passwords. In normal applications, passwords are hashed with a random salt that is stored along with them to prevent them from being bruteforced easily.

However, we could just use username, password and the same salt for every record in the database. This option would save one data field for each record, while the combination of username and password would be unique for our entire database. Is such a solution just as safe as the traditional password hashing scheme, or are there some security drawbacks to them I am not aware of?

  • 4
    $\begingroup$ Look, here's the thing. Say your salts are 256 bits long, which is an entirely reasonable size. That's 30 megabytes per million users. How is this an issue? Just use bcrypt and move on to dealing with problems that are actually worth your time solving. Saving a few tens of megabytes is not one of them. $\endgroup$ – Stephen Touset Jan 25 '13 at 22:05
  • 1
    $\begingroup$ This answer to a bit different question on Security StackExchange is very good: security.stackexchange.com/questions/11221/… $\endgroup$ – dchest Jan 26 '13 at 1:29
  • $\begingroup$ @StephenTouset I am not implementing such a system myself, I'm just curious about the problem. This question is just to satisfy that curiosity. $\endgroup$ – ThePiachu Jan 26 '13 at 7:56
  • 1
    $\begingroup$ The unique salt per password is there to prevent an attacker from amortizing his effort over many passwords. If you use the same salt for n passwords you make his job easier by a factor of n. Note that the salt is not secret. $\endgroup$ – starblue Jan 26 '13 at 9:50
  • 2
    $\begingroup$ @starblue Yes, but a single salt plus unique username would prevent the attacker from amortising their effort as they would not be able to look for more than one user's password at a time. $\endgroup$ – ThePiachu Jan 26 '13 at 10:43

Let's try to avoid random per-password salts. If the only requirement for salt is to be unique, which is the case for good password hashing schemes, you'll need:

  • $globalSalt$ is a secret random 32-byte string.
  • $userId_n$ is a unique user identifier.

You can use, for example, $HMAC$-$SHA256(globalSalt, userId_i)$ to generate salt for each user $i$. Or, with PBKDF2 or scrypt, you can just concatenate the values of $globalSalt$ and $userId_i$.

This scheme achieves uniqueness for salt only when you don't allow users to change their passwords. If you do, salt will be unique per user, not per password, so if someone changes their password, their salt will stay the same. In which case, if there are database leaks at, say, three points in time, given that the salt is unique per user, not per password, the attacker gets some information about passwords (e.g. if the user changed their password to the same value.)

To make salt unique per password, you also have to include some counter of password changes, which you have to update and store, and concatenate with $userId$. Storing this counter per-user defeats the original intention, so you can have a single global counter, making sure it never repeats, in which case you can also drop $userId$ and just use this counter along with $globalSalt$.

If $globalSalt$ is leaked, the only advantage the attacker gets is that he will be able to precompute future hashes for current and future $userId$s, which doesn't seem very useful.

We avoided generating and storing random salts by building a more complex and less secure system. Thus, it's much simpler and more secure, as others said, to use random salts instead of bothering with implementing your own scheme.

| improve this answer | |
  • 2
    $\begingroup$ You said it yourself: the only requirement for a salt is to be unique. This approach does not preserve this property in a system where users can change passwords. A user who changes his password will still reuse the same salt, and the requirement of uniqueness is violated. $\endgroup$ – Stephen Touset Jan 26 '13 at 1:13
  • 1
    $\begingroup$ I considered the case of changing passwords later in the answer. We get system which leaks some information about passwords if there are multiple leaks of database. Is it bad? Yes. Is it better than a single per-database salt? Yes. Is it worse than random salt? Of course. $\endgroup$ – dchest Jan 26 '13 at 1:20
  • $\begingroup$ Again, the question was: are there drawbacks in the system where we don't use /dev/urandom to generate salts? I listed them. I'll try to rephrase my answer. $\endgroup$ – dchest Jan 26 '13 at 1:38
  • 1
    $\begingroup$ That's fine. It seemed like your original answer was encouraging the practice of a static per-user salt. Your edits are an improvement. $\endgroup$ – Stephen Touset Jan 26 '13 at 5:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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