Expand description
cSHAKE256 and KMAC256 targeting post-quantum security.
§Post-quantum security rationale
The classical crypto-prf crate uses BLAKE3, which produces 256-bit output. Under
Grover’s quantum search algorithm, a brute-force preimage attack on an n-bit hash
drops from O(2^n) to O(2^(n/2)) quantum operations, halving the effective security
level. A 256-bit digest therefore provides only ~128 bits of post-quantum preimage
resistance — acceptable today, but below the 256-bit target required for long-lived
or high-assurance systems.
cSHAKE256 addresses this in two ways:
-
512-bit output (64 bytes). Grover halves the exponent, so a 512-bit output retains ~256 bits of post-quantum preimage resistance — matching AES-256’s quantum security level and the NIST PQC security category 5 target. Note that Grover’s amplitude amplification is inherently sequential and does not parallelise efficiently: k quantum processors yield only a √k speedup rather than k, making the practical attack cost far higher than the theoretical exponent alone suggests.
-
NIST-standardized sponge construction. SHAKE256 is defined in FIPS 202 and uses a 1600-bit Keccak-p[1600,24] permutation with a 512-bit capacity. The large capacity means a quantum collision search (BHT algorithm) still requires O(2^(capacity/3)) ≈ O(2^170) operations, well above the 128-bit quantum collision-resistance floor. BHT additionally assumes quantum random-access memory (QRAM) storing O(2^(capacity/3)) quantum states — an unsolved engineering problem that makes the full attack purely theoretical at this capacity.
BLAKE3, by contrast, is built on a Merkle tree of BLAKE2 compression functions optimised for software throughput; it was not designed with a formal post-quantum security analysis and has received less scrutiny in that context than the SHA-3 family.
§Keccak, SHA-3, SHAKE, cSHAKE, and KMAC
These five names refer to a single family, each layer building on the one below.
§Keccak
Keccak is the underlying permutation: Keccak-p[1600,24] operates on a 1600-bit state and applies 24 rounds of a fixed bijective transformation. It won the NIST hash-function competition in 2012 and is the only primitive this entire family trusts. Everything above it — SHA-3, SHAKE, cSHAKE, KMAC — is just framing around the same permutation.
§SHA-3
SHA-3 (FIPS 202, 2015) is the fixed-length hash standardisation of Keccak. It pads the message, absorbs it into the sponge, and squeezes out exactly 224, 256, 384, or 512 bits. SHA-3-256 and SHA-3-512 are the drop-in replacements for SHA-256 and SHA-512. The “256” in SHA-3-256 is the output length. Internally, SHA-3-256 uses a 512-bit capacity (2 × output length), and appends a domain-separation byte (0x06) before padding.
§SHAKE
SHAKE (also FIPS 202) replaces the fixed output with an extendable output function (XOF): after absorbing the message you can squeeze out as many bytes as you need. SHAKE128 and SHAKE256 differ only in capacity:
| Variant | Capacity | Security level | Domain byte |
|---|---|---|---|
| SHAKE128 | 256 bits | 128 bits | 0x1f |
| SHAKE256 | 512 bits | 256 bits | 0x1f |
The “256” in SHAKE256 is the security level, not the output length — you
choose the output length at call time. SHAKE256 with 64-byte output is what
this module uses for its DIGEST_LEN default.
SHA-3 and SHAKE are distinct: they use different domain bytes (0x06 vs 0x1f), so SHA-3-256(x) ≠ SHAKE256(x)[0..32] even though both use the same permutation and the same capacity.
§cSHAKE
cSHAKE (NIST SP 800-185, 2016) adds customization to SHAKE via two additional string parameters absorbed before the message:
- N (function name): a string reserved for NIST-defined algorithms.
User code always passes
"". - S (customization string): an arbitrary application-defined string. Two cSHAKE calls with different S values produce completely independent output spaces, even with the same key and message.
When both N and S are empty, cSHAKE falls back to plain SHAKE (same output),
so cSHAKE is a strict superset. The CShake256::digest(customization) and
CShake256::shake256() constructors below expose this distinction.
§KMAC
KMAC (also SP 800-185) is the keyed layer: it sets N="KMAC" (domain-
separating it from all cSHAKE uses), then absorbs a key block encoded via
bytepad(encode_string(key), rate) before the message, and appends
right_encode(output_length_bits) at finalization. The result is a
NIST-approved MAC, PRF, and KDF in one construction.
The full hierarchy:
Keccak-p[1600,24] (permutation, FIPS 202)
└── SHA-3-{224,256,384,512} fixed-length hash, domain 0x06
└── SHAKE{128,256} XOF, domain 0x1f
└── cSHAKE{128,256} + N/S customization strings (SP 800-185)
└── KMAC{128,256} + key block + length suffix (SP 800-185)Structs§
Constants§
- DIGEST_
LEN - Default output length: 64 bytes (512 bits) for 256-bit post-quantum preimage resistance.
Functions§
- digest
- cSHAKE256(
customization,input), producingDIGEST_LENbytes. - hmac
- KMAC256(
key,customization,input), producingDIGEST_LENbytes. - kdf
- KMAC256-based KDF(
key_material,customization), producingNbytes. - shake256
- SHAKE256(
input), producingDIGEST_LENbytes.