HKDF Key Derivation (RFC 5869, extract-expand)
Derive keys with HKDF and see both halves: the PRK from extract, every T block from expand, and the OKM in hex and base64. RFC 5869 cases built in.
How to use
- Put in the input keying material. Each field reads hex by default and has a checkbox to treat it as text instead, so you can paste a shared secret as bytes or type a label as characters.
- Add a salt if you have one and an info string that names what the key is for — the protocol, the direction, the version. Both may be empty, and the page says what it substitutes when the salt is.
- Choose the hash and the output length in bytes. The limit shown is 255 times the hash output, which is where the specification stops.
- Read the PRK, the T blocks and the OKM. The line underneath says whether the browser’s own HKDF returned the same bytes; if it ever says otherwise, do not use the output.
About this tool
ShowHide
HKDF is the key derivation function that turns one strong secret into as many independent keys as you need, and it is two steps rather than one. Extract compresses the input keying material into a fixed-width pseudorandom key: PRK = HMAC-Hash(salt, IKM), which is all the extract step is. Expand then stretches that PRK into output of any length by chaining HMACs, T(i) = HMAC(PRK, T(i-1) ‖ info ‖ i), and cutting the concatenation to size. This page shows both, which matters because the browser will not.
crypto.subtle.deriveBits fuses extract and expand into one call and never returns the PRK. The HKDF key object is not exportable either — asking for its bytes raises InvalidAccessError — so there is no way to see the intermediate value through the API at all. This tool therefore computes both steps itself out of HMAC, prints the PRK and each T block, and then asks the browser for the same answer and tells you whether the two agree. Two implementations concurring is worth more than one asserting.
The info field is the part most people skip and the reason HKDF exists in the shape it does. The same IKM and salt with different info produce keys with no computable relationship, which is how TLS 1.3 gets a separate key for each direction and each purpose from one handshake secret, rather than slicing one long output into pieces and hoping. If you are deriving more than one key from one secret, they should differ in info, not in offset.
Two limits the specification imposes and the browser enforces. The output is capped at 255 × HashLen — 8160 bytes for SHA-256 — because the block counter appended inside expand is a single byte; ask for more and both this page and deriveBits refuse. And an absent salt becomes HashLen zero bytes, which reads like a convention until you try it: Web Crypto rejects a zero-length HMAC key with DataError: HMAC key data must not be empty, so without the substitution the extract step could not be computed in a browser at all.
The four presets are test cases 1, 3, 4 and 7 of RFC 5869, so you can confirm the page against the specification in one click: case 1 gives a PRK of 077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5 and an OKM beginning 3cb25f25faacd57a. Case 3 is the same IKM with no salt and no info, which lands somewhere completely different — 19ef24a32c717b16… — because the extract step is not a formality.
One thing HKDF is not: a password KDF. It runs a single HMAC per output block, with no iteration count and no memory cost, so it hands an attacker guessing passwords no work at all. It assumes its input is already high-entropy. For a password, reach for PBKDF2, scrypt or Argon2 instead.
Frequently asked questions
Why does the tool show a PRK when Web Crypto does not?
Because the PRK is the thing you need when you are matching another implementation and the outputs differ: it tells you whether the disagreement is in extract or in expand. crypto.subtle.deriveBits performs both steps in one call and returns only the final bytes, and the imported HKDF key cannot be exported — exportKey raises InvalidAccessError. Since extract is literally HMAC-Hash(salt, IKM), the page recomputes it with crypto.subtle.sign and shows it.
What is info for, and can I leave it empty?
You can leave it empty, and RFC 5869 allows that, but info is what makes HKDF worth using over a bare hash. It binds the derived key to a context, so the same secret yields unrelated keys for unrelated purposes. Use something unambiguous and versioned — an application label, a direction, a protocol version — and concatenate its parts in a way that cannot be confused, since "ab" ‖ "c" and "a" ‖ "bc" are the same bytes.
Why is the output limited to 255 blocks?
Expand appends a one-byte counter to each HMAC input, so it can only count to 255. That gives 5100 bytes with SHA-1, 8160 with SHA-256 and 16320 with SHA-512. If you need more than that, you almost certainly want several derivations with different info rather than one enormous output, which is better practice anyway.
Can I use HKDF on a password?
You can, and you should not. HKDF computes one HMAC per output block — it is designed to be fast, because its input is assumed to already be unguessable. A password is guessable, and the whole job of a password KDF is to make each guess expensive through iterations or memory. PBKDF2 with a high iteration count, scrypt, or Argon2 are the right tools; HKDF is what you use afterwards, on the key those produce, if you need several keys from it.
Is the salt secret?
No. It can be public, sent in the clear, or omitted. Its job is to make extract behave as a randomness extractor over a wider class of inputs, not to hide anything. That said, a salt is worth having when you can manage one: it makes the analysis stronger and costs you nothing. What must stay secret is the IKM and everything derived from it.
Related tools
PBKDF2 Key Derivation
Derive a key from a password with PBKDF2-HMAC in your browser — pick the hash, iteration count and output length, and read the result as hex or Base64.
Developer
scrypt Key Derivation (RFC 7914)
Derive a key from a password with scrypt in the browser, with the memory cost worked out and the PBKDF2 and ROMix stages shown.
Developer
DNSSEC Calculator — DS Record & NSEC3 Hash
Turn a DNSKEY into the DS record your registrar wants — key tag and all three digest types — or hash a name the way NSEC3 does.
Network
Keypair Generator (RSA, EC, Ed25519)
Generate an RSA, ECDSA, ECDH, Ed25519 or X25519 keypair in your browser and export it as PKCS#8 and SPKI PEM or as JWK.
Developer
AES-GCM Encrypt / Decrypt (key, nonce, AAD)
Encrypt and decrypt with AES-GCM in your browser: hex key and nonce, optional AAD, selectable tag length, and the ciphertext and tag kept apart.
Developer
Base32 Encoder / Decoder
Encode and decode Base32 (RFC 4648), with standard and base32hex variants — useful for TOTP secrets and Crockford-style IDs.
Developer