HKDF: HMAC-Based Key Derivation
TLS 1.3 and the Signal Protocol both lean on the same small, elegant primitive to turn a shared secret into however many separate keys they actually need. Here's how HKDF's extract-then-expand design works.
Interactive HKDF Visualizer
🔐 HKDF Key Derivation
HKDF: HMAC-Based Key Derivation
Introduction
Real protocols almost never need just one key. TLS needs separate keys for encryption and authentication, in each direction. The Signal Protocol derives a fresh key for every single message via its Double Ratchet. Almost universally, these systems start with one shared secret — the output of a Diffie-Hellman exchange, for instance — and need to turn it into several independent, cryptographically strong keys. HKDF (HMAC-based Key Derivation Function), standardized in RFC 5869, is the standard tool for exactly this job.
Table of Contents
- The Extract-then-Expand Design
- Step 1: Extract
- Step 2: Expand
- Why Separate Extract and Expand?
- A Verified Example
- Real-World Applications
- FAQ
- References
The Extract-then-Expand Design
HKDF splits key derivation into two distinct steps, each doing one job well:
- Extract: concentrate the entropy from a (possibly not perfectly random) input, like a raw Diffie-Hellman shared secret, into a fixed-size, uniformly random-looking pseudorandom key (PRK).
- Expand: stretch that PRK into as many bytes of output key material as needed, optionally binding in context information to produce distinct keys for distinct purposes from the same PRK.
Both steps are built entirely from HMAC (covered in its own HMAC guide) with a chosen underlying hash function — no new cryptographic primitives, just a carefully specified way of combining an already-trusted one.
Step 1: Extract
PRK = HMAC-Hash(salt, input_key_material)
The salt is optional (an all-zero value is used if omitted) but strongly recommended when available — even a non-secret salt meaningfully strengthens the extraction step, especially when the input key material’s randomness quality isn’t perfectly guaranteed.
Step 2: Expand
T(0) = empty string
T(1) = HMAC-Hash(PRK, T(0) | info | 0x01)
T(2) = HMAC-Hash(PRK, T(1) | info | 0x02)
T(3) = HMAC-Hash(PRK, T(2) | info | 0x03)
...
OKM = T(1) | T(2) | T(3) | ... truncated to the requested length
The info parameter lets you derive multiple independent keys from the same PRK just by varying a context string — for example, deriving a distinct encryption key and a distinct authentication key from the same underlying shared secret, without needing two separate extraction steps.
Interactive Visualizer
The visualizer above runs the real HKDF-SHA256 construction — genuine extract and expand steps built on real HMAC-SHA256 — and was verified against a standard cryptographic library’s HKDF implementation before being published here.
Why Separate Extract and Expand?
Input key material isn’t always uniformly random — a Diffie-Hellman shared secret, for instance, is a specific number within a mathematically structured group, not an arbitrary random string, even though it’s unpredictable to an attacker. The Extract step’s entire job is converting that structured, possibly-uneven input into something statistically indistinguishable from a uniformly random key before any further derivation happens — a formally analyzed property that gives HKDF’s overall security proof a clean foundation to build on, rather than hoping the raw input’s randomness properties are good enough on their own.
A Verified Example
Using RFC 5869-style parameters:
- Input key material: “input key material”
- Salt: “salt value”
- Info: “context info”
- Output length: 42 bytes
produces a specific, deterministic 42-byte output key material value — exactly what the visualizer above reproduces, matching a standard cryptographic library’s HKDF-SHA256 output byte for byte.
Real-World Applications
- TLS 1.3: uses HKDF extensively throughout its key schedule, deriving all traffic keys, handshake keys, and various intermediate secrets from the initial (EC)DHE shared secret.
- Signal Protocol: the Double Ratchet’s per-message key derivation is built on HKDF, expanding chain keys into message keys with each step.
- WireGuard: uses HKDF (via its Noise Protocol Framework foundation) for deriving session keys during its handshake.
- General protocol design: whenever a system has one shared secret and needs several independent-looking keys for different purposes, HKDF is close to the default, well-analyzed answer.
FAQ
What’s the difference between HKDF and PBKDF2?
They solve different problems: HKDF is designed to expand an already-high-entropy secret (like a Diffie-Hellman output) into multiple derived keys efficiently. PBKDF2 is designed to slow down brute-forcing a low-entropy password, deliberately taking much longer per derivation. Using HKDF directly on a user password (skipping the deliberate slowness) would be insecure; using PBKDF2 where HKDF’s speed and multi-key expansion are needed would be needlessly slow and awkward.
Is the salt required for HKDF?
No, but it’s recommended whenever one is available. RFC 5869 defines the behavior when no salt is provided (defaulting to a string of zero bytes), and even a non-secret, non-random salt still meaningfully improves the Extract step’s security properties.
What’s the “info” parameter actually for?
It’s a context-binding string that lets you derive multiple, cryptographically independent keys from a single PRK — for example “encryption key” versus “authentication key” as the info string — without needing to run the (potentially more expensive) Extract step more than once.
Can HKDF be used with any hash function?
Yes — RFC 5869 defines HKDF generically over any hash function usable with HMAC; HKDF-SHA256 is the most common choice in modern protocols, though HKDF-SHA1 and other variants exist in older or legacy systems.
Why not just use the shared secret directly as a key?
A raw Diffie-Hellman shared secret has structure (it’s an element of a specific mathematical group) that a truly random key wouldn’t have, and using it directly provides no way to derive multiple distinct keys for multiple purposes from a single exchange. HKDF’s extract step normalizes that structure away, and the expand step handles multi-key derivation cleanly.
References
-
RFC 5869. “HMAC-based Extract-and-Expand Key Derivation Function (HKDF).” IETF, 2010. Available at: https://datatracker.ietf.org/doc/html/rfc5869
-
Krawczyk, H. “Cryptographic Extraction and Key Derivation: The HKDF Scheme.” CRYPTO 2010 — the academic paper behind HKDF’s design and security analysis.
-
Wikipedia. “HKDF.” Available at: https://en.wikipedia.org/wiki/HKDF