HKDF vs PBKDF2 in plain language

Published: 2026-09-05

When to use PBKDF2 for password stretching vs HKDF for expanding high-entropy key material—salt, iterations, info strings, and deriving keys locally with Web Crypto.

Key derivation functions (KDFs) turn input secrets into fixed-length keys for encryption, MACs, or protocol handshakes. Two names show up constantly in Web Crypto and backend docs: PBKDF2 and HKDF. They solve related but different problems. Mixing them up leads to weak password storage or pointless “iterations” on already-random keys.

This guide compares them in plain language, maps parameters to what you paste into tools, and shows why deriving keys in the browser keeps passphrases and IKM off servers.

Same family, different jobs

PBKDF2 HKDF
Best for Stretching a human password / passphrase Expanding high-entropy key material (IKM)
Slow on purpose? Yes — iterations burn CPU against guessing No — designed to be fast
Core inputs Password, salt, iteration count, hash IKM, optional salt, optional info, hash
Typical output 16–64 bytes of key material Any length you need (within hash limits)
RFC / vibe Password-Based Key Derivation Function 2 RFC 5869 extract-and-expand

Rule of thumb: if a human might type or remember the secret, start with PBKDF2 (or a modern password hash like Argon2 / scrypt). If you already have a strong random secret (DH shared secret, master key, token bytes), use HKDF to carve out labeled subkeys.

PBKDF2: stretch passwords with salt and work

PBKDF2 repeatedly runs a keyed hash (PRF) so each guess costs real time:

  1. Take the password and a random salt.
  2. Run HMAC (SHA-256, etc.) in a loop for N iterations.
  3. Output dkLen bytes of derived key material.

Salt ensures identical passwords produce different outputs and defeats rainbow tables. Iterations are the dial for offline attack cost. Higher is safer and slower—pick a count that is painful for attackers but acceptable for your UX (login, unlock, or local encrypt).

Parameter Role Practice
Password Low-entropy secret Prefer long passphrases; never reuse across sites
Salt Unique per credential Random, store alongside the derived key / hash
Iterations Work factor Raise over time as hardware improves
Hash / PRF HMAC-SHA-256 (or stronger) Prefer SHA-256+; SHA-1 only for legacy vectors

Empty salts are fine for lab experiments and RFC test vectors. In production, generate a fresh salt per password and store it. PBKDF2 alone is not a complete password-storage design (you still need format, pepper policy, and upgrade path)—but it is the Web Crypto–native way to stretch a passphrase into AES or HMAC key bytes.

HKDF: expand strong secrets with context

HKDF (HMAC-based Key Derivation Function) assumes the input is already high entropy—a shared secret from ECDH, a master key from a CSPRNG, or similar. It has two conceptual stages (often combined in one API call):

  1. Extract — mix IKM with an optional salt into a fixed pseudorandom key (PRK).
  2. Expand — stretch that PRK to the length you need, mixing in an application info string.

Info (also called “context” or “label”) binds the derived bytes to a purpose: aes-gcm-v1, hmac-webhook, client-write-key. Same IKM with different info yields different keys, so one master secret can safely feed many roles without reuse.

Parameter Role Practice
IKM Input keying material Random or protocol-derived; not a typed password
Salt Optional domain separator Random salt strengthens extract; empty is allowed
Info Purpose / context Stable ASCII labels your protocol documents
Length Bytes to derive Match AES-128/256, HMAC keys, etc.

Do not “fix up for security” by running millions of PBKDF2 iterations on an ECDH shared secret and calling it HKDF. Use HKDF (or a KDF designed for that protocol). Conversely, do not feed a short user password into HKDF and expect iteration-like resistance—HKDF will not save a weak passphrase.

When to pick which

Situation Prefer
Derive an AES key from a user passphrase PBKDF2 (high iterations + unique salt)
Turn one master key into “encrypt” and “MAC” keys HKDF with different info strings
Password login / stored credential verifier Password hash (Argon2/scrypt) or carefully tuned PBKDF2
Post-handshake key schedule (TLS-like) HKDF-style extract-and-expand
Matching an old Java/.NET Rfc2898DeriveBytes sample PBKDF2 with the same salt, iterations, hash, length
Matching an RFC 5869 test vector HKDF with the published IKM, salt, info, L

Web Crypto exposes both: deriveBits / deriveKey with PBKDF2 or HKDF. LocalTools’ playground wraps the same APIs so you can compare outputs without writing boilerplate.

Encoding traps (UTF-8 vs hex)

Passwords are usually UTF-8 text. Salts, IKM, and info are often raw bytes shown as hex in specs. One mismatched encoding (treating hex as UTF-8, or dropping a leading zero nibble) changes every derived byte.

Checklist before blaming the algorithm:

  • Same hash (SHA-256 vs SHA-384 vs SHA-512; PBKDF2 may still use SHA-1 in legacy code).
  • Same byte length of salt / IKM / info (not just the same printable string).
  • Same output length.
  • Same iteration count (PBKDF2 only).
  • Hex inputs have even length and no 0x / spaces unless your tool strips them.

Derive keys locally

Online “password to key” pages that upload your passphrase create an unnecessary trust surface: the input is the long-term secret. Prefer:

  1. Web Crypto in the browser (or a known-good CLI).
  2. Parameters you can set to match a protocol or test vector.
  3. Hex / Base64 copy-out without network round-trips.

LocalTools’ HKDF & PBKDF2 Playground runs entirely in-tab: choose PBKDF2 or HKDF, set UTF-8 or hex for salt (and IKM/info in HKDF mode), pick SHA-256/384/512 (or SHA-1 for PBKDF2 legacy), set iterations or info, derive 1–512 bytes, and copy hex or Base64. Passphrases and key material never leave the device.

Common pitfalls

  • Using HKDF on a typed password — no meaningful work factor; use PBKDF2 (or Argon2) first.
  • Using PBKDF2 on random IKM “for safety” — slow and the wrong abstraction; use HKDF + info labels.
  • Reusing salt across users — defeats uniqueness; generate per credential.
  • Iterations too low — comfortable UX today may be cheap for GPU clusters tomorrow.
  • Ignoring info — omitting context when the other side includes it yields different keys and silent decrypt failures.
  • SHA-1 by default — fine only when matching legacy vectors; prefer SHA-256+ for new work.

Try it in the browser

Use the HKDF & PBKDF2 Playground to:

  1. Derive 32 bytes with PBKDF2 from a passphrase, salt, and a few thousand iterations; copy hex.
  2. Switch to HKDF with a long random IKM and two different info strings; confirm the outputs diverge.
  3. Replay an RFC or library test vector with hex encodings until your summary parameters and output match.

Related reading: AES-GCM basics (nonce, tag, AAD) for what derived keys often encrypt, Password strength beyond “8 characters” for passphrase quality before stretching, Generating passwords and tokens in the browser for CSPRNG material, and Why “local only” matters for developer tools for the privacy model.

All learn articles