One of the typical approaches to computing a salted hash is this:


where hash is something like SHA-256 hash function - taking any size input and returning fixed size output. What's the need for the hash(secret)?

Why can't I just do this:

hash(salt + secret)

where + is simply concatenating two byte arrays?

  • 1
    $\begingroup$ I don't see any reason here. Do you have some examples where it is used this way? $\endgroup$ Commented Jun 9, 2012 at 12:44
  • $\begingroup$ @Paŭlo Ebermann: I've seen in multiple times in comments to a post about recent LinkedIn passwords leakage. $\endgroup$
    – sharptooth
    Commented Jun 9, 2012 at 12:46
  • 4
    $\begingroup$ The only reason I can think of is for hiding the clear text password on the network. Consider that with $H(salt || pwd)$, in a very simple system, the user would send $pwd$ and the server would compute the hash to check. Anybody who can sniff the password from the network now cannot only log in, but also knows the password. With $H(salt || H(pwd))$ he can only sniff the hash. He can now log in, but would still need a preimage attack to find out the actual password. $\endgroup$
    – Maeher
    Commented Jun 9, 2012 at 12:56
  • $\begingroup$ LinkedIn did not know the secret, they only knew hash_without_salt(secret). That's what they stored in their database. So unless they waited for every person to login, the only way to add a salt, is to take the stored unsalted hash as input. $\endgroup$ Commented Jun 11, 2012 at 14:30

1 Answer 1


This construction has two advantages over a plain hash of param1||param2:

  • It's immune to length-extensions
  • You can't get collisions of the form param1=A||B param2=C vs. param1=A param2=B||C.

But neither of those is relevant to password hashing, so it doesn't offer any advantage there.

The construction looks like it's inspired by HMAC:

$$ HMAC(K,m) = H((K ⊕ opad) ∥ H((K ⊕ ipad) ∥ m)) $$

But of course for password hashing one would not use such fast hashing constructions. Correct choices are scrypt, bcrypt, and PBKDF2. These have a designated salt parameter, so they don't need such an ad-hoc construction to mix salt and password.

This system has one big advantage though: You can upgrade existing hashes to it, without knowing the plaintext password. Essentially you treat $ hash(pass) $ as the new password. When upgrading an old system from a plain, unsalted hash, I'd use something like:

$ PBKDF2(LegacyHash(password), salt) $

  • $\begingroup$ A negation is missing in the first sentence of the last paragraph. $\endgroup$
    – fgrieu
    Commented Jun 9, 2012 at 13:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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