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.