# Concat KDF (SP 800-56C): The Two-Step Approach

**Source**: https://quantumsequrity.com/blog/concat-kdf-nist
**Category**: Standards & Documents

---

[← Back to Blog](../../blog.html) Standards & Documents

# Concat KDF (SP 800-56C): The Two-Step Approach

11 min read

When two parties run a key agreement protocol, the output is a shared secret that both sides can compute independently. That secret might come from a Diffie-Hellman exchange, an Elliptic Curve Diffie-Hellman, or a post-quantum key encapsulation mechanism like ML-KEM. Whatever the source, the raw output is rarely the right size or shape to use directly as a cryptographic key. It needs to pass through a key derivation function first.

NIST Special Publication 800-56C tells you which KDFs are approved for that role and how to use them. The document was first published in 2011 and revised most recently in 2020 as Rev. 2. It is the companion to SP 800-56A (Diffie-Hellman) and SP 800-56B (RSA-based key transport). If you are deriving keys from a key-establishment shared secret in a FIPS-compliant system, this is the document you must follow.

This article explains what SP 800-56C says, what the Concat KDF is, how it has evolved into a two-step extract-then-expand model, and how it relates to HKDF and the rest of the NIST KDF family.

## The Original Concat KDF

The earliest version of the Concat KDF, sometimes called the One-Step KDF, was simple. Take the shared secret Z and a context string, hash them together with a counter, and produce as much output as needed:

OKM = Hash(counter_1 || Z || OtherInfo) || Hash(counter_2 || Z || OtherInfo) || ...

This is essentially the X9.63 KDF (covered in [KDF1, KDF2, KDF3: ANSI X9.63 Derivation Functions](kdf1-kdf2-kdf3-x963)) under a different name. The hash is typically SHA-256, SHA-384, or SHA-512. The counter is a 32-bit big-endian integer starting at 1.

OtherInfo is structured. NIST gives a recommended format that concatenates several fields:

AlgorithmID || PartyUInfo || PartyVInfo || SuppPubInfo || SuppPrivInfo

AlgorithmID identifies the cryptographic algorithm the derived key will be used with. PartyUInfo and PartyVInfo identify the two parties (often X.509 subject names or hashes thereof). SuppPubInfo includes any other public context, like a session ID or transcript hash. SuppPrivInfo is rarely used and contains private context if any.

Each field has a length prefix so that fields can be parsed back unambiguously. This is critical: without length prefixes, two different OtherInfo strings could collide and produce the same key in different sessions.

The original one-step KDF was approved as long as Z was sampled uniformly enough. NIST waved this through with the assumption that DH or ECDH outputs were "near-uniform" enough for the hash to extract sufficient entropy.

## Why Two Steps Became the Norm

By the late 2000s, cryptographers understood that the "near-uniform" assumption was sloppy. Diffie-Hellman shared secrets live on a curve or in a subgroup; their bits have structure. An attacker who learns partial information might recover bits of Z faster than expected if the KDF treats Z naively.

Hugo Krawczyk's 2010 paper on HKDF formalized the right approach: split derivation into two steps, Extract and Expand. Extract takes the messy Z and produces a clean uniform pseudorandom key (PRK). Expand takes the PRK and stretches it to whatever length you need. We covered this paradigm in [HKDF (RFC 5869) Line by Line](hkdf-rfc-5869-deep-dive) and the abstract pattern in [Two-Step Key Derivation](two-step-key-derivation).

NIST adopted this thinking in SP 800-56C Rev. 1 (2011) and refined it in Rev. 2 (2020). The current document supports two derivation methods:

The one-step KDF, which is the original concat KDF.

The two-step KDF, which is HKDF-style: a randomness extractor followed by a key expansion function.

Both are FIPS-approved, but the two-step KDF is now preferred for new designs.

## The Two-Step KDF in Detail

In the two-step KDF, the Extract step produces a fixed-length PRK from Z and an optional salt. The approved Extract functions are HMAC-Hash and KMAC. The Expand step then produces the actual output key material.

Extract:

PRK = MAC(salt, Z)

where MAC is HMAC-Hash or KMAC, salt is a non-secret value (often a session-specific nonce or transcript hash, or zero bytes if no salt is available), and Z is the shared secret.

Expand:

OKM = SP 800-108 counter mode KDF (PRK, label = "", context = OtherInfo, L)

The Expand step uses SP 800-108 counter mode (covered in [NIST SP 800-108 Counter Mode KDFs](sp-800-108-kdf)) with the PRK as the master key. The Label is conventionally empty and the Context is the OtherInfo string.

Note how this matches HKDF almost exactly:

HKDF-Extract: PRK = HMAC(salt, Z)
HKDF-Expand: OKM = stretching of PRK with info string

The two-step SP 800-56C KDF is essentially HKDF written in NIST's vocabulary. The interoperability gap between IETF and NIST has nearly closed.

## The One-Step KDF Lives On

Despite the move to two-step, the one-step KDF is still approved in SP 800-56C Rev. 2 because so many existing systems use it.

The one-step KDF is parameterized by an auxiliary function H, which can be:

A hash function (SHA-256, SHA-384, SHA-512, SHA3-256, SHA3-384, SHA3-512).

HMAC with one of those hashes.

KMAC.

The general structure is:

OKM = H(counter_1, Z, OtherInfo) || H(counter_2, Z, OtherInfo) || ...

When H is a plain hash, this is the original concat KDF. When H is HMAC or KMAC, it is a strengthened variant where a nonzero salt can be passed as the MAC key.

The advantage of the one-step form is simplicity. Implementations only need one primitive call per output block. The disadvantage is that the entropy extraction is less rigorous than in the two-step form.

For FIPS modules supporting both SP 800-56A (key agreement) and SP 800-56B (key transport), the choice between one-step and two-step is left to the implementer, with the proviso that the inputs must be high-entropy.

## How It Fits with ML-KEM and Post-Quantum

The arrival of post-quantum KEMs has put SP 800-56C in the spotlight. NIST FIPS 203 (ML-KEM, formerly Kyber) defines a key encapsulation mechanism that produces a 32-byte shared secret K. To use that shared secret as a session key, you typically pass it through a KDF first.

The natural choice is SP 800-56C's two-step KDF with HMAC-SHA-256. The Extract step compresses K with a salt (often a transcript hash). The Expand step produces the per-purpose subkeys.

In hybrid constructions that combine ML-KEM and X25519, you concatenate the two shared secrets and pass them to Extract:

Z_hybrid = K_ml_kem || K_x25519
PRK = HMAC-SHA-256(salt, Z_hybrid)
session_keys = SP 800-108 counter mode (PRK, ..., L)

This pattern appears in IETF drafts, in NIST SP 800-227 (the upcoming KEM key-establishment companion to FIPS 203), and in our own [Hybrid Encryption](hybrid-encryption) discussion.

For details on ML-KEM itself, see [ML-KEM Explained](ml-kem-explained).

## OtherInfo Best Practices

OtherInfo (or info, or context, depending on the spec) is the place where you bind the derivation to a specific protocol session. Mistakes here are a common source of cross-protocol attacks.

Best practices:

Always include a unique algorithm identifier. If your derived key is for AES-256-GCM, say so. Two protocols using AES-128 and AES-256 should produce different keys.

Always include party identifiers when applicable. In a client-server setting, include the client's identity and the server's identity, or hashes thereof.

Include a session-specific binding value, like a transcript hash or a unique session ID. This prevents a key derived in one session from being usable in another.

Use length-prefixed encoding for variable-length fields. NIST gives a specific format with 4-byte length prefixes for each substring. Follow it.

Do not include secrets in OtherInfo. The OtherInfo is treated as public; including a secret does not strengthen the derivation and may leak through error messages or logs.

## Where SP 800-56C Is Used

In FIPS 140-3 validated modules, the Concat KDF or its two-step descendant is the approved KDF for key agreement. RSA, DH, ECDH, and ML-KEM all flow through SP 800-56C.

In NIST's own protocols, like the Suite B and CNSA guidance referenced in [2035 NSA CNSA Deadline Plan](2035-nsa-cnsa-deadline-plan), SP 800-56C is the named KDF.

In TLS implementations that aim for FIPS compliance, the implementation typically maps the TLS HKDF-based key schedule onto an SP 800-56C two-step KDF call internally, since both are essentially the same construction.

In smart card and EMV systems, the older one-step KDF is most common because of legacy compatibility.

In hybrid PQC libraries (like the open-quantum-safe project), SP 800-56C's two-step KDF is one of the supported derivation functions for combining ML-KEM and classical shared secrets.

## Implementation Pitfalls

Salt handling. The salt in Extract should be non-secret but should vary per session if possible. A constant zero salt is allowed but defeats the purpose of binding derivations to specific sessions.

OtherInfo encoding. Implementations sometimes hardcode the OtherInfo format and silently truncate or pad. Read the spec for your platform; FIPS 140-3 testing covers OtherInfo format compliance.

Hash choice mismatch. If two interoperating systems use different hashes (one SHA-256, one SHA-384), they will not derive the same key. Negotiate the hash explicitly in the protocol.

Output length encoding. Some implementations pre-encode the requested L into a fixed field and silently truncate if the caller asks for more bytes. Others allow up to 255 hash blocks. Know your implementation.

Z byte order. ECDH shared secrets must be encoded in a canonical byte order before hashing. Check whether your implementation uses the X-coordinate only or the full point, and whether it uses big-endian or little-endian encoding. The two implementations on either end must agree.

## How to Pick Between One-Step and Two-Step

For new designs, prefer two-step. It has the cleanest security argument, it lines up with HKDF for IETF interoperability, and it is what NIST recommends going forward.

For legacy interoperability, you may need one-step. EMV, ANSI X9.63 ECIES, and older banking protocols all use one-step. You can implement both in a library and select based on the negotiated suite.

For internal NIST FIPS 140-3 module designs, two-step with HMAC-SHA-256 is the default safe choice.

## Frequently Asked Questions

### Is SP 800-56C the same as HKDF?

The two-step variant is essentially HKDF with NIST naming. In practice, you can implement HKDF and call it SP 800-56C two-step KDF as long as the salt and context handling matches the spec. FIPS validation labs accept this equivalence.

### What hash should I use?

SHA-256 for 128-bit security strength. SHA-384 for 192-bit. SHA-512 for 256-bit (and higher quantum-era strength). For SHA-3, the corresponding functions are SHA3-256, SHA3-384, and SHA3-512. KMAC256 with KMAC256 in Extract gives full 256-bit symmetric strength.

### Can I derive keys for AES-128 and AES-256 from the same shared secret?

Yes. Use SP 800-56C with two different OtherInfo strings, one specifying "AES-128" and the other "AES-256". The two derived keys will be independent.

### Does SP 800-56C protect against quantum attacks?

The KDF itself is post-quantum-safe under standard hash assumptions. Grover's algorithm gives at most a square-root speedup against keyed hash search, which the strong NIST hashes accommodate. The bigger question is whether the input Z is post-quantum-safe. ECDH is not; ML-KEM is.

### Is the one-step KDF deprecated?

Not yet. SP 800-56C Rev. 2 still approves it. New designs should prefer two-step, but existing one-step deployments do not need to migrate immediately.

## Sources

1. NIST Special Publication 800-56C Rev. 2. "Recommendation for Key-Derivation Methods in Key-Establishment Schemes." August 2020. https://csrc.nist.gov/pubs/sp/800/56/c/r2/final
2. NIST Special Publication 800-56A Rev. 3. "Recommendation for Pair-Wise Key-Establishment Schemes Using Discrete Logarithm Cryptography." April 2018. https://csrc.nist.gov/pubs/sp/800/56/a/r3/final
3. NIST Special Publication 800-56B Rev. 2. "Recommendation for Pair-Wise Key-Establishment Using Integer Factorization Cryptography." March 2019. https://csrc.nist.gov/pubs/sp/800/56/b/r2/final
4. NIST Special Publication 800-108 Rev. 1. "Recommendation for Key Derivation Using Pseudorandom Functions." August 2022. https://csrc.nist.gov/pubs/sp/800/108/r1/final
5. Krawczyk, H. "Cryptographic Extraction and Key Derivation: The HKDF Scheme." IACR ePrint 2010/264. https://eprint.iacr.org/2010/264
6. NIST FIPS 203. "Module-Lattice-Based Key-Encapsulation Mechanism Standard." August 2024. https://csrc.nist.gov/pubs/fips/203/final

## Related Articles

- [HKDF (RFC 5869) Line by Line](hkdf-rfc-5869-deep-dive)
- [Two-Step Key Derivation: Extract Then Expand](two-step-key-derivation)
- [NIST SP 800-108 Counter Mode KDFs Explained](sp-800-108-kdf)
- [KDF1, KDF2, KDF3: ANSI X9.63 Derivation Functions](kdf1-kdf2-kdf3-x963)
- [Hybrid Encryption: Why Combining Old and New Crypto Is Stronger](hybrid-encryption)

---

### Protect Your Data Before Q-Day Arrives

QNSQY's NIST-standardized post-quantum encryption protects files against both current and quantum-era threats.

[Try QNSQY](../../pricing.html)
