Key Derivation Functions

The two different jobs called "KDF" — stretching low-entropy passwords versus expanding high-entropy secrets — why HKDF splits extract from expand, and why context binding is what stops cross-protocol key reuse.

"KDF" names two jobs that share a word and almost nothing else. One turns a low-entropy human password into a key and must be deliberately slow. The other turns an already-strong secret — a Diffie–Hellman output, a master key — into several independent keys and must be fast. Using the wrong family for the job is a real and common bug: a password through HKDF is brute-forceable, and a DH secret through Argon2 is a pointless performance tax.

Password-based KDF Key-expansion KDF
Input low entropy (~20-40 bits) high entropy (≥128 bits)
Threat offline brute force none from guessing
Design goal expensive (time + memory) cheap, provably a PRF
Examples Argon2id, scrypt, bcrypt, PBKDF2 HKDF, SP 800-108 KDFs, TLS 1.3 schedule
Covered in password storage this entry

Why not just hash it #

The naive key = SHA256(shared_secret) fails for reasons that are structural, not stylistic:

  • A Diffie–Hellman output is a group element, not a uniform bit string. Its bits are biased and it carries algebraic structure — for a finite-field DH the result is always a quadratic residue, which alone leaks a bit.
  • Merkle–Damgård hashes are length-extendable, so H(secret ‖ context) constructions are unsafe as MACs and fragile as KDFs.
  • You usually need several keys (send/receive, encryption/MAC), and they must be independent — recovering one must not reveal the others.
  • Nothing binds the key to the context it was derived for, which is what enables cross-protocol reuse attacks.

HKDF: extract, then expand #

Krawczyk's HKDF (RFC 5869) is the standard answer, and its contribution is separating two distinct operations that ad-hoc KDFs conflate:

PRK=HMAC(salt⏟key, IKM⏟message)\text{PRK} = \text{HMAC}(\underbrace{salt}_{\text{key}},\ \underbrace{IKM}_{\text{message}})

OKM=HMAC(PRK,Ti−1 ∥ info ∥ i)  concatenated until enough bytes\text{OKM} = \text{HMAC}(\text{PRK}, T_{i-1} \,\|\, info \,\|\, i) \ \text{ concatenated until enough bytes}

Extract takes non-uniform input keying material (IKM) and condenses it into a uniformly random pseudorandom key (PRK). Note the inversion: the salt is the HMAC key and the secret is the message — deliberate, so that extraction is sound even when the salt is public or absent.

Expand stretches the PRK into as many output bytes as needed, using a counter and an info string.

The three inputs each do a specific job:

Input Required? Purpose
IKM yes the secret being derived from
salt optional but recommended de-correlates derivations across sessions; may be public and non-secret; strengthens the extraction proof
info optional but use it binds the output to a purpose — this is the key-separation mechanism

What TLS 1.3 does with it #

TLS 1.3 derives its entire key hierarchy from HKDF, and the design is worth studying as the reference application:

Two properties fall out of this structure. Every derivation runs HKDF-Expand-Label, which mixes in a label and the handshake transcript hash — so keys are bound not just to a purpose but to the exact negotiated parameters, which kills whole classes of downgrade and cross-protocol attack. And the chained extracts mean a compromise of one stage's secret doesn't hand over the others.

Choosing and using #

  • Deriving several keys from a strong secret → HKDF-SHA256. If the input is already uniform (a random 32-byte master key), HKDF-Expand alone suffices.
  • FIPS-constrained → NIST SP 800-108 KDFs in counter mode with HMAC or CMAC.
  • From a password → never HKDF. Use Argon2id; see password storage.
  • From a DH/ECDH output → HKDF-Extract with the handshake transcript as salt, then Expand per key.
  • Modern all-in-one → BLAKE3 has a native derive_key mode with a domain-separation context string, and is fast enough to make the extract/expand distinction moot for most uses.

Sources

  1. docsRFC 5869 — HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
  2. paperCryptographic Extraction and Key Derivation: The HKDF Scheme (Krawczyk, 2010)
  3. docsRFC 8446 — The Transport Layer Security (TLS) Protocol Version 1.3
  4. docsNIST SP 800-108 Rev. 1 — Recommendation for Key Derivation Using Pseudorandom Functions

Searches titles, aliases, headings, summaries, and full text.↑↓ move ↵ open esc close