Key Derivation Functions (PBKDF2, HKDF)

Learn about key derivation functions: PBKDF2 for password-based key derivation and HKDF for deriving multiple keys from a master secret. Includes Web Crypto API examples and parameter guidance.

Practical Examples

Detailed Explanation

Key Derivation Functions: PBKDF2 and HKDF

Key Derivation Functions (KDFs) transform input keying material into one or more cryptographically strong keys. Two KDFs are supported by the Web Crypto API and are widely used in modern applications: PBKDF2 and HKDF.

PBKDF2: Password-Based Key Derivation

PBKDF2 (Password-Based Key Derivation Function 2) converts a human-memorable password into a high-entropy encryption key. It uses three mechanisms to resist brute-force attacks:

  1. Salt — A random value that prevents precomputed dictionary attacks (rainbow tables)
  2. Iteration count — Repeats the hash function many times, making each guess expensive
  3. Hash function — Typically SHA-256 or SHA-512
// Web Crypto API — PBKDF2
const passwordBytes = new TextEncoder().encode("user-password");
const salt = crypto.getRandomValues(new Uint8Array(16));

const baseKey = await crypto.subtle.importKey(
  "raw", passwordBytes, "PBKDF2", false, ["deriveKey"]
);

const aesKey = await crypto.subtle.deriveKey(
  {
    name: "PBKDF2",
    salt: salt,
    iterations: 600000,  // OWASP 2023 recommendation
    hash: "SHA-256",
  },
  baseKey,
  { name: "AES-GCM", length: 256 },
  false,
  ["encrypt", "decrypt"]
);

Iteration Count Guidelines

The iteration count should be as high as tolerable for your use case:

Year OWASP Recommendation (SHA-256)
2017 100,000
2021 310,000
2023 600,000

Higher iteration counts directly increase the time required for each password guess, but also increase legitimate key derivation time. Target 100-500ms on your target hardware.

HKDF: Extract-and-Expand Key Derivation

HKDF (HMAC-based Key Derivation Function) derives one or more keys from a high-entropy secret (not a password). It operates in two phases:

  1. Extract — Condenses the input key material into a fixed-length pseudorandom key
  2. Expand — Generates the required number of output key bytes using an info parameter
// Derive multiple keys from a shared secret
const sharedSecret = /* from ECDH key agreement */;

const baseKey = await crypto.subtle.importKey(
  "raw", sharedSecret, "HKDF", false, ["deriveKey", "deriveBits"]
);

// Derive an encryption key
const encryptionKey = await crypto.subtle.deriveKey(
  { name: "HKDF", hash: "SHA-256",
    salt: new Uint8Array(0),
    info: new TextEncoder().encode("encryption") },
  baseKey,
  { name: "AES-GCM", length: 256 },
  false, ["encrypt", "decrypt"]
);

// Derive a separate authentication key
const authKey = await crypto.subtle.deriveBits(
  { name: "HKDF", hash: "SHA-256",
    salt: new Uint8Array(0),
    info: new TextEncoder().encode("authentication") },
  baseKey,
  256
);

PBKDF2 vs HKDF: When to Use Each

PBKDF2 HKDF
Input Low-entropy password High-entropy secret
Purpose Make brute-force expensive Derive multiple keys
Slowness Intentionally slow Fast
Iterations 600,000+ N/A
Use case Password → encryption key Shared secret → multiple keys

Important Distinctions

  • Never use HKDF on passwords — HKDF is fast and offers no brute-force resistance
  • Never use PBKDF2 to derive multiple keys — Use PBKDF2 to derive one master key, then HKDF to derive sub-keys
  • Always use a unique salt with PBKDF2 — Two users with the same password should get different keys
  • Use the info parameter in HKDF to separate keys for different purposes (encryption vs authentication)

Alternatives to PBKDF2

For password hashing (not browser-compatible via Web Crypto):

  • Argon2 — Memory-hard, winner of the Password Hashing Competition
  • scrypt — Memory-hard, used in some cryptocurrency protocols
  • bcrypt — Time-tested, widely supported

These are preferred for server-side password hashing but are not available in the Web Crypto API.

Use Case

Key derivation functions are essential for any application that derives encryption keys from passwords. Browser-based encryption tools (encrypted note apps, file encryption, password managers) use PBKDF2 to convert user passwords into AES keys. The TLS and Signal protocols use HKDF to derive session keys from key agreement outputs. Understanding the distinction between PBKDF2 (slow, for passwords) and HKDF (fast, for secrets) prevents one of the most common cryptographic design errors.

Try It — Encryption Playground

Open full tool