10
$\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
  • 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
    Commented Jan 7, 2018 at 22:00

3 Answers 3

14
$\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$
2
  • 1
    $\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
    Commented Jan 10, 2018 at 19:35
  • 1
    $\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$ Commented Jan 10, 2018 at 20:07
8
$\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 (2018), 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.


Update: PBKDF2 is very obsolete (2024), just avoid it. That's what password cracking attackers with GPUs, FPGAs or ASICs hope you are using when it comes to purposely costly password-to-key transformation. Use something memory-hard: Argon2 if possible, or scrypt if more available (it's bundled in Python). Even the lesser and obsolete bcrypt is preferable.

$\endgroup$
7
  • $\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
    Commented Jan 10, 2018 at 19:34
  • 2
    $\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$ Commented Jan 12, 2018 at 13:02
  • 1
    $\begingroup$ So the whole point of using PBKDF2 over HMAC in key derivation is to slow it down? $\endgroup$
    – Cyker
    Commented Jul 6, 2018 at 13:02
  • 2
    $\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
    Commented Jul 6, 2018 at 14:20
  • $\begingroup$ I don't think bcrypt should be being described as 'lesser' or 'obsolete' when it's supposedly preferable to Argon2 for <1000 ms of delay (basically all password hashing). It also has an incredibly simple cost parameter, whereas memory-hard algorithms have difficult to set parameters (memory, iterations, and parallelism). It's stood the test of time and is still used. $\endgroup$ Commented Jul 25 at 21:44
6
$\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$

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.