I once heard that if implementing a password hashing scheme, simply concatenating the password and salt together before hashing could lead to some subtle vulnerabilities, and I'm trying to figure out if this is actually the case.

According to this anecdote, the following should not be used:

hash(salt + password)
hash(password + salt)

And instead, something similar to an HMAC, like the following, should be used:

hash(hash(password) + salt)

Even though simple concatenation is vulnerable to length extension, I can't think of a way that could ever be useful to an attacker.

Is there any merit to this anecdote?

  • 1
    $\begingroup$ None of these constructs are secure, and unfortunately, length extension attacks have nothing to do with it. Please just use bcrypt or scrypt. See this answer for more details. $\endgroup$ – Stephen Touset Feb 7 '16 at 21:52
  • $\begingroup$ I see information about why those libraries are useful, but I don't see any information about why these are insecure. Perhaps you could explain? (This is actually a theoretical question, I do not currently have need of a password hashing tool). $\endgroup$ – IanPudney Feb 7 '16 at 22:08
  • 1
    $\begingroup$ @IanPudney: All three schemes are insecure against attack on the stored hashes due to being fast enough to compute that they can be brute-forced. I think you are correct in thinking the HMAC variant offers no advantage for password storage (in fact it just seems like confusion that "HMAC is better for signing messages" carried over to passwords), but that does not mean any of them are considered good nowadays. If your anecdote was received recently from a source reputing to know about password security, then that source needs updating. $\endgroup$ – Neil Slater Feb 7 '16 at 23:04

One difference is that with simple concatenation two different salt-password pairs could lead to the same hash input. For example: H('abcd'||'example@example.com') = H('abcde'||xample@example.com). This cannot happen between your password hashes if you use a constant width salt, but could still happen between your password hashes and those of some other service using the same hash.

With HMAC or another construction that handles the password and salt differently you avoid such collisions. Collisions still exist, of course, if the number of possible passwords and salts is long enough, but they never happen in practice.

If you generate a long enough random salt you avoid the issue even with simple concatenation, and that is usually a good idea in any case, so the practical effect may not be significant in many applications.

In practice the issue should not crop up other than in algorithm design. The best practice is always to use a real password-hashing function, such as bcrypt, scrypt or argon2, and those expose an iterface where you input the salt and password separately.


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.