5
$\begingroup$

Being a software developer, I haven't dealt with crypto so far. So I know very little, sorry for that already.

I am aware that you should use bcrypt, scrypt, Argon2 or PBKDF2 for generating a hash from a password. However, I have a question about PBKDF2.

DK = PBKDF2(PRF, Password, Salt, c, dkLen)

PBKDF2 uses a pseudorandom function, for example HMAC-SHA256.

What I understand is that PBKDF2 uses HMAC-SHA256 for c iterations. Why not just use HMAC-SHA256 directly?

I know that you should not use SHA256 for passwords because it's basically "too efficient". So, is HMAC-SHA256 way less efficient, and if so why cannot we use it direclty?

Why does PBKDF2 need a PRF?

Perhaps you can explain it so that even I, who has not much to do with crypto stuff, can understand it. ;-)

$\endgroup$
  • 1
    $\begingroup$ HMAC essentially does two calls to the underlying hash function per HMAC-call. It is meant to be an efficient construction (though for message authentication). $\endgroup$ – SEJPM Jan 7 '18 at 22:00
7
$\begingroup$

HMAC is still very efficient. It's used in PBKDF2 not for the lower efficiency (that's handled by iterating it many times) because of the fact that it takes two inputs. That lets the password and other data be combined in a safe manner, invlunerable to some of the issues that just using SHA256 alone could create.

PBKDF2 isn't doing H(H(H(...H(Pwd + salt))...), it's doing HMAC(Pwd, HMAC(Pwd, ... HMAC(Pwd, Salt + number)...), where + denotes concatenation and the number is a block index. So the iterations use the password as the key for the HMAC in each stage, and stages other than the first are HMACing the output of the previous stage. This mixes the password in to every iteration of the result, instead of just the first iteration.

Hopefully that explains both why HMAC alone isn't enough and the obvious follow-up question of why HMAC instead of just SHA-256.

$\endgroup$
  • $\begingroup$ I was missing some info that was too large for a comment, but I've got no problem at all recommending this answer. $\endgroup$ – Maarten Bodewes Jan 8 '18 at 13:57
  • $\begingroup$ Well, your answer has some info mine doesn't as well (the variable length output of PBKDF2, etc.) But the core idea that "HMAC = fast, but multi-input" is in both. $\endgroup$ – SAI Peregrinus Jan 8 '18 at 17:55
  • $\begingroup$ Thanks for your answer! But why cannot I just use SHA256 or another hash function with say 100,000 iterations? It would also slow down SHA256, no? $\endgroup$ – Aliquis Jan 10 '18 at 19:35
  • $\begingroup$ It would slow down SHA2, but it wouldn't have the resistance to length extension attacks that HMAC does. It might be possible to use SHA-512/256 and a construction to mix the key in each iteration securely, but the performance would be about the same as for HMAC-SHA256 anyway and would create more room for error in the design. HMAC has been well analyzed, so PBKDF2's designers took advantage of that work instead of making their own equivalent. More modern password hashing algorithms like Bcrypt and Argon2 use different permutations entirely, and so don't rely on any form of HMAC internally. $\endgroup$ – SAI Peregrinus Jan 10 '18 at 20:07
5
$\begingroup$

HMAC-SHA-256 with a static key is actually about as efficient as just SHA-256. Yes, it uses SHA-256 twice, but with a given key a lot of pre-computation can be performed.

PBKDF2 relies on the iteration count (a linear work factor) alone for the key strengthening. So we cannot directly use HMAC-SHA-256 as it doesn't strengthen the password at all. Note that key strengthening only provides a relatively limited amount of protection; using a difficult to guess password is still required.

Besides that, HMAC only provides a static amount of output: the output is identical to the hash size. So there is no way to expand that output to a higher amount of bits. PBKDF2 does provide such functionality, although mistakes in the scheme should prevent you from ever using it.


PBKDF2 doesn't really need a PRF. But as you may note, the password can be used directly as a key in the HMAC function. So it makes sense that a PRF is used.

If you would be using a hash function then you must specify a secure scheme to include the multi-parameter input and generate the output. Most of this work is already performed in HMAC. HMAC is a very sturdy algorithm that already protects against known weaknesses of SHA-256 such as length extension attacks.

Finally, the input key material of HMAC is expected to have to remain secret. This can make a difference when it comes to protecting the input material in the specific runtime environment.

$\endgroup$
4
$\begingroup$

What's the difference between PBKDF2 and HMAC-SHA256 in security?

PBKDF2 has a parameter c to slow it down, and that makes it suitable to turn a password into a key or password hash with a controllable speed/security compromize. HMAC-SHA256 has nothing to slow it down, is much faster than PBKDF2 with a reasonable c, and that makes HMAC-SHA256 a very poor choice to process a password, from a security standpoint.

PBKDF2 uses HMAC-SHA256 for c iterations. Why not just use HMAC-SHA256 directly?

Because we would miss the c parameter, which would essentially be set to 1 or other small value. The difficulty/cost of password cracking grows about linearly with c, typical values of c are (or should be) in the order of 100000 or more nowadays (growing with Moore's law to maintain security at a constant level). That's why there's a large and increasing loss of security we would get using HMAC-SHA256 rather than PBKDF2.

Is HMAC-SHA256 way less efficient (than SHA-256)?

No. HMAC-SHA256 tries to be as fast a PRF (or MAC; sort of, a hash with a key) as one can build from SHA-256. For long input hashed, they are nearly as fast. For short input, HMAC-SHA256 might be 3 times slower than SHA-256, or so.

Why does PBKDF2 needs a PRF?

That allows PBKDF2 to have some demonstrable security properties. Some parts of PBKDF2 could use SHA-256 rather than HMAC-SHA256 (and do without the key input of HMAC-SHA256, or prepend that key to what's hashed), and using HMAC-SHA256 slows down PBKDF2 to some degree. But PBKDF2's speed must be kept under precise control (using the c parameter, which controls security) when it processes a password, thus there is no speed penalty in using HMAC-SHA256, at constant security.


PBKDF2 is obsolete, and should be replaced by something like bcrypt, scrypt, Argon2.. that leverages memory for better security at a given cost or time for the legitimate user. But PBKDF2 with a large c is still largely better than directly hashing a password with a hash or HMAC.

$\endgroup$
  • $\begingroup$ Thanks for your answer! But why cannot I just use SHA256 or another hash function with say 100,000 iterations? It would also slow down SHA256, no? $\endgroup$ – Aliquis Jan 10 '18 at 19:34
  • $\begingroup$ @Aliquis, you should probably read about salting and rainbow tables. A message digest (like SHA256) does not takes a single input. HMAC-SHA256 takes two inputs, in this case salt and password, providing defense against rainbow tables. PBKDF2 then makes everything slower, providing defense against dictionary attacks. $\endgroup$ – Erwan Legrand Jan 12 '18 at 13:02
  • $\begingroup$ So the whole point of using PBKDF2 over HMAC in key derivation is to slow it down? $\endgroup$ – Cyker Jul 6 '18 at 13:02
  • 1
    $\begingroup$ @Cyker: the whole point is slowing down the equivalent operation a password search is bound to perform; that implies slowing down legitimate key derivation too, but that's an unwanted side effect. Slowing down key derivation by writing it in javascript would be pointless, because password crackers are not bound to use javascript. $\endgroup$ – fgrieu Jul 6 '18 at 14:20

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.