Skip to content
apikey.tools
HMACSignatures

Key Derivation Function Sandbox

Derive independent keys from one master secret, and feel what the cost parameter actually costs.

HMACRuns in this tabInput not transmitted

Input

Vary this to derive independent keys from one master secret.

100000

Watch the derivation time change. That time is what an attacker pays per guess.

Output

computing

Two different jobs get called "key derivation", and conflating them causes real problems.

Password stretching turns a low-entropy human password into a key, slowly, so attackers pay for every guess. Cost is the whole point. That is what PBKDF2 key derivation covers.

Key separation turns one high-entropy master secret into many independent keys, one per purpose. Speed is fine; cost buys nothing, because there is no guess space to defend.

This sandbox is for exploring both, and for developing intuition about the cost parameter by watching the derivation time move.

Key separation, and why it matters

Using one secret for several purposes couples them. Encrypt with the same key you sign with, and a weakness in one construction can undermine the other. Rotate for one reason, and you rotate for all of them.

The fix is to derive a distinct key per purpose from a single master, using the context string as the differentiator:

master  = <256 bits from a secure generator>

app:v1:encryption  -> AES-GCM data key
app:v1:signing     -> HMAC key for tokens
app:v1:cookies     -> session signing key

Each derived key is independent: recovering one reveals nothing about the master or the others. You store and rotate one secret, and every derived key changes with it.

Include a version in the context. When you need to rotate, move to app:v2: and every derived key changes together, in a controlled way.

What the cost slider teaches

Move it and watch the derivation time. That number is what an attacker pays per guess.

At 1,000 iterations the derivation is instant, and so is the attacker's. At 600,000 it takes a noticeable fraction of a second, and the attacker's billion-guesses-per-second becomes a few thousand.

For key separation from a high-entropy master, low cost is correct — there is nothing to slow down. For password stretching, high cost is the entire mechanism. The right parameter depends on which job you are doing.

HKDF is the right primitive for separation

PBKDF2 is used here because Web Crypto provides it and the behaviour is illustrative. For key separation specifically, HKDF (RFC 5869) is the correct choice: it is designed for exactly this, it is fast, and it takes an explicit info parameter for the context.

Web Crypto supports HKDF via deriveBits with { name: "HKDF", hash, salt, info }. If you are implementing key separation in production, use that rather than PBKDF2 with a low iteration count.

Frequently asked questions

Can I derive an AES key directly?

Yes. Set the output to 256 bits and the result is a valid AES-256 key. In code, crypto.subtle.deriveKey produces a CryptoKey directly, which is better than deriving bits and importing them because the key material never becomes a JavaScript value.

Does the salt need to be secret?

No. Its job is uniqueness, not secrecy. For password stretching it must be random and unique per password. For key separation it is a context label and should be descriptive.

Why derive keys instead of generating and storing several?

You store and protect one secret rather than five. Rotation is one operation. And you cannot accidentally deploy a service with the wrong key, because each service derives only the key its context names.

Should I use this for production key derivation?

Use the same construction, implemented server-side with HKDF. This sandbox exists to make the parameters tangible, not to derive keys you deploy from a browser tab.

More signatures tools

Compute and verify request signatures