Encryption

How Key Derivation Functions Work

Understand how key derivation functions like HKDF and PBKDF2 transform secrets into strong encryption keys, and when to use each type for secure systems.

Editorial Team ·
9 min read intermediate

Introduction

When TLS 1.3 completes a Diffie-Hellman key exchange, both parties have computed the same 32-byte shared secret. But that secret is never used directly to encrypt data. Instead, it is fed into a key derivation function — and from a single shared secret, TLS derives separate keys for handshake traffic, application traffic, and resumption tickets, each cryptographically independent. If you were to use the raw Diffie-Hellman output as an encryption key, you would be violating a fundamental rule of applied cryptography: never use a secret directly if you can derive from it. The Signal protocol, WireGuard, IPsec, and every modern secure messaging system follow the same rule. Getting key derivation wrong means that compromising one session key cascades into compromising all of them.

A key derivation function (KDF) is a cryptographic algorithm that transforms a source secret into one or more keys suitable for use in encryption, authentication, or other cryptographic operations. Unlike hashing, which is designed for integrity verification, a KDF is designed to produce keying material with specific properties: the correct length, uniform randomness, and independence between derived outputs. The same KDF primitive, applied with different context labels, produces completely different keys — that is the design guarantee that TLS 1.3’s security model depends on.

This article explains the two main categories of KDFs, how the most important KDFs work (HKDF and PBKDF2), what distinguishes them from each other, and where each is correctly applied. Whether you are reviewing the argon2id vs PBKDF2 question for password storage, understanding the TLS handshake key schedule, or configuring a key management system, this foundation will anchor every decision you make about key material.

What Is a Key Derivation Function?

A key derivation function takes an input secret — called input key material (IKM) — and produces output that is safe to use as an encryption key. The problem KDFs solve is that raw secrets often have defects that make them unsuitable for direct use in cryptographic algorithms: they may be too short, statistically biased, or in the wrong format. A Diffie-Hellman shared secret, for example, is not uniformly random — it lies on an elliptic curve and has mathematical structure that could theoretically be exploited if used directly.

KDFs solve this by conditioning the input through a cryptographic function — typically an HMAC or a hash — that produces output that is uniformly distributed regardless of the input’s structure. This conditioning process is called key extraction. Many KDFs go further and perform key expansion: from a single extracted key, they derive multiple independent output keys, each tied to a specific purpose through a context label.

KDFs fall into two distinct categories based on the nature of their input:

  • High-entropy KDFs: Designed for inputs that already have significant entropy — master keys, Diffie-Hellman outputs, hardware RNG seeds. These KDFs focus on conditioning and expanding, not adding computational cost. HKDF is the primary example.
  • Password-based KDFs (PBKDFs): Designed for low-entropy inputs — user passwords and passphrases. These KDFs deliberately add computational work (iterations, memory requirements) to make brute-force guessing expensive. Argon2id, PBKDF2, bcrypt, and scrypt are examples.

Confusing these two categories is one of the most dangerous errors in applied cryptography. Applying a fast, high-entropy KDF to a password provides no resistance to GPU-based cracking. Applying a slow PBKDF to a high-entropy key wastes computational resources for no security benefit.

How Key Derivation Functions Work

HKDF: Extract Then Expand

HKDF (HMAC-based Key Derivation Function) is defined in RFC 5869 and is the most widely deployed high-entropy KDF. TLS 1.3 uses HKDF as its entire key schedule. The Signal Double Ratchet, WireGuard, and Noise protocol use it for session key derivation.

HKDF works in two stages, named the Extract-then-Expand design:

Extract. The input key material (a Diffie-Hellman output, a hardware seed, a master key) is mixed with a salt — a non-secret random value — using HMAC-SHA-256 or HMAC-SHA-512. The output is a fixed-length pseudorandom key (PRK). The purpose of this step is to take whatever the input looks like — biased, structured, variable length — and produce something that is computationally indistinguishable from random. The salt is not secret; its role is to ensure that two different applications of the same IKM produce different PRKs.

Expand. The PRK is then stretched into as many output keys as needed, each identified by a context label (called info in RFC 5869). Each call to the Expand step with a different label produces a completely different derived key. TLS 1.3 uses labels like “tls13 handshake traffic secret” and “tls13 application traffic secret” to derive the handshake keys and session keys from the same master secret — they are independent because their context labels differ.

The critical property of HKDF is that no output key can be used to recover any other output key, even if both were derived from the same PRK. This is what cryptographers call computational independence between derived keys.

PBKDF2: Password-Based Key Stretching

PBKDF2 (Password-Based Key Derivation Function 2) is defined in RFC 8018 and NIST SP 800-132. Unlike HKDF, which is designed for high-entropy inputs, PBKDF2 is designed specifically for user passwords — which typically contain only 40 to 60 bits of entropy at best.

PBKDF2 works by applying a pseudorandom function (typically HMAC-SHA-256) to the password and a random salt, then repeating that application a configurable number of times — the iteration count. The output of one iteration becomes the input of the next, chaining the applications sequentially.

The iteration count is the security parameter. At 100,000 iterations of HMAC-SHA-256, a single PBKDF2 computation takes roughly 100ms on a modern CPU — slow enough to frustrate brute-force attacks but fast enough for login flows. However, GPUs can run PBKDF2 in parallel at millions of guesses per second, making Argon2id — which adds a memory requirement that resists GPU parallelism — the preferred choice today for new systems.

The salt in PBKDF2 is non-secret but must be unique per credential. Its purpose is to prevent precomputation attacks: without a salt, an attacker could build a table of PBKDF2 outputs for common passwords once and look up millions of credentials instantly. With a unique per-credential salt, every credential requires a fresh brute-force attempt.

Notice how HKDF and PBKDF2 differ in their design intent: HKDF conditions and expands high-entropy material, while PBKDF2 iterates over low-entropy passwords to add computational cost.
This video explains how HKDF implements the extract-then-expand design at a mathematical level. HKDF is the foundational KDF used in TLS 1.3 and represents the core design principle all high-entropy KDFs share. Watch specifically for the HMAC chaining in the Expand stage.

KDF vs Password-Based KDF: Choosing the Right One

This comparison captures the key decision dimensions when selecting a KDF for your system.

CriterionHKDF (RFC 5869)PBKDF2 (RFC 8018)Argon2id
Input entropy assumptionHigh (DH output, master key)Low (password, passphrase)Low (password, passphrase)
Computational costFast (milliseconds)Configurable (iterations)Configurable (time + memory)
GPU resistanceN/A — not for passwordsLow — parallelizableHigh — memory-hard
Multiple output keysYes — via context labelsNo — single outputNo — single output
NIST recommendationSP 800-108 (expansion)SP 800-132 (passwords)Not yet FIPS-approved
FIPS 140 complianceYesYesNo (not FIPS-approved)
Used in TLS 1.3Core key scheduleNoNo
Used for password storageWrong toolAcceptableRecommended
Standard referenceRFC 5869RFC 8018, NIST SP 800-132Password Hashing Competition

The most important takeaway is column separation: HKDF is never correct for passwords, and PBKDF2/Argon2id are never correct for deriving session keys from high-entropy material.

Real-World Use Cases

TLS 1.3 key schedule. The entire TLS 1.3 key schedule, defined in RFC 8446 Section 7.1, is built on HKDF. After the Diffie-Hellman exchange produces a shared secret, HKDF.Extract derives a master secret, and HKDF.Expand then derives the handshake traffic secret, the application traffic secret, and the resumption master secret — all from the same root, all independent because of different context labels. This means that even if an attacker somehow obtained the application traffic key, it could not be used to compute the handshake keys or resumption keys. This design is described in detail in our TLS handshake explainer.

Envelope encryption in cloud KMS. AWS KMS, Azure Key Vault, and GCP KMS use a hierarchical key structure. Your data is encrypted with a data encryption key (DEK), and the DEK is encrypted with a key encryption key (KEK) stored in the KMS. When the KMS generates DEKs, it uses an internal KDF to derive multiple DEKs from a single root key material, ensuring each DEK is independent. This prevents a compromised DEK from revealing the root key or any sibling DEK. Our key management services guide explains how this hierarchy works in practice.

Password authentication in web applications. When a user creates an account, the application runs PBKDF2 or Argon2id on the password with a random salt, stores the output and the salt (never the password), and discards the input. When the user logs in, the same KDF with the stored salt is run on the entered password, and the outputs are compared. If the database is stolen, the attacker must run the KDF for each password guess — a GPU-resistant function like Argon2id makes this cost prohibitive for all but the weakest passwords. The published Argon2id vs PBKDF2 comparison covers the parameter recommendations in detail.

Common Mistakes to Avoid

Using a raw hash as a key. SHA-256 of a secret is not a key derivation function. It has no salt, produces no context separation, and for low-entropy inputs like passwords, a GPU can reverse it trivially. Always use a purpose-built KDF, never a raw hash, when producing keying material.

Using HKDF for password hashing. HKDF is fast by design. Applying it to a user password produces a key in microseconds — fast enough for legitimate use but also fast enough for an attacker to run billions of guesses per second on a GPU. Password storage demands a deliberately slow, memory-hard function. Using HKDF for password storage is equivalent to storing a plaintext-equivalent credential.

Reusing the same derived key for multiple purposes. If you use a single derived key for both encryption and authentication (MAC), a theoretical weakness in one context could compromise the other. HKDF’s context-label mechanism exists precisely to prevent this: derive a separate key for each purpose using a different info label. This is the same principle behind TLS 1.3 deriving separate keys for handshake and application data.

Setting PBKDF2 iteration count too low. NIST SP 800-132 recommended 10,000 iterations as a minimum in 2010, but hardware has improved dramatically. OWASP now recommends at minimum 600,000 iterations of PBKDF2-HMAC-SHA-256 for new systems. Anything below 100,000 is dangerously fast on modern hardware. For FIPS-compliant environments where Argon2id is not an option, recalibrate your iteration count annually as hardware improves.

Not rotating derived keys when the root changes. If a master key or root secret is rotated, all keys derived from it must be considered compromised and re-derived. KDF output is only as secure as the input it came from. Implement automated re-encryption workflows triggered by root key rotation — the concepts in our encryption key rotation guide apply directly to KDF hierarchies.

Getting Started

Choose HKDF for session keys and key hierarchies. If you are building a protocol, managing session keys, or implementing envelope encryption, use HKDF with distinct, descriptive context labels for each derived key. The IETF’s RFC 5869 is a five-page document; read it before implementing. Modern cryptographic libraries (libsodium, Bouncy Castle, Go’s crypto/hkdf package, Python’s cryptography library) all provide vetted HKDF implementations.

Choose Argon2id for password storage. For new systems, OWASP recommends Argon2id with a minimum of 19 MiB of memory, 2 iterations, and 1 degree of parallelism. For FIPS-compliant environments where Argon2id is not available, use PBKDF2-HMAC-SHA-256 with at least 600,000 iterations and ensure your iteration count is documented in a configuration variable — not hardcoded — so you can increase it without a code change.

Validate your key schedule against the spec. If you are implementing TLS or a similar protocol, test your HKDF key schedule against the known-answer test vectors published in RFC 5869 and the TLS 1.3 test vectors from the RFC 8448 appendix. A KDF implementation error is silent — incorrect keys simply cause decryption failures, and without test vectors, you may not detect the error until production.

Pair KDF choice with a robust hardware security module strategy. For production key hierarchies, root keys and master key material should never exist in plaintext outside of an HSM. The KDF derives working keys from the root, but the root’s security is the foundation of the entire hierarchy. A compromised root renders all derived keys insecure, regardless of how strong the KDF is.

FAQ

Common questions — answered in plain English.

What is a key derivation function and why is it needed?
A key derivation function (KDF) is a cryptographic algorithm that transforms a source secret — such as a password, a Diffie-Hellman shared secret, or a master key — into one or more cryptographically strong encryption keys. Raw secrets are often biased, too short, or in the wrong format for encryption algorithms; a KDF refines them into keys with the correct length and statistical uniformity.
What is the difference between HKDF and PBKDF2?
HKDF is designed for high-entropy inputs like Diffie-Hellman shared secrets and master keys, extracting and expanding them into multiple derived keys. PBKDF2 is designed for low-entropy inputs like user passwords, adding computational cost through iteration to slow down brute-force attacks. Using HKDF on a password, or PBKDF2 on a high-entropy key, is a security mistake.
What is the HKDF extract-then-expand design?
HKDF works in two stages. The Extract stage mixes the input key material with a salt to produce a fixed-length pseudorandom key (PRK), regardless of the input's quality or format. The Expand stage then stretches that PRK into multiple derived keys of any length, using context labels to ensure the keys are cryptographically independent from each other.
How are key derivation functions used in TLS 1.3?
TLS 1.3 uses HKDF extensively throughout the handshake. After the Diffie-Hellman key exchange produces a shared secret, HKDF derives separate handshake traffic keys and application traffic keys. Each key is independent and bound to a specific context label, ensuring that compromising one key does not reveal any other.
Is PBKDF2 still secure to use?
PBKDF2 is still considered acceptable but is no longer the recommended choice. Argon2id — the winner of the Password Hashing Competition — is now the OWASP and NIST preferred option because it is resistant to both GPU-based and side-channel attacks. Bcrypt and Scrypt are also acceptable. PBKDF2 remains in use primarily for legacy compatibility and FIPS-compliant environments.
What is the difference between a KDF and a hash function?
A hash function maps an input to a fixed-length output and is designed for integrity verification — not for producing encryption keys. A KDF produces keying material specifically designed for use in cryptographic algorithms, with properties like independent outputs, proper length, and resistance to related-key attacks. Using a raw SHA-256 hash as an encryption key is insecure; using HKDF to derive that key is correct.

References

  1. [1]
  2. [2]
  3. [3]
  4. [4]
  5. [5]