Skip to main content

Module cshake256

Module cshake256 

Source
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:

  1. 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.

  2. 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:

VariantCapacitySecurity levelDomain byte
SHAKE128256 bits128 bits0x1f
SHAKE256512 bits256 bits0x1f

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§

CShake256
Reader
A streaming reader over the XOF output of a finalized CShake256 instance.

Constants§

DIGEST_LEN
Default output length: 64 bytes (512 bits) for 256-bit post-quantum preimage resistance.

Functions§

digest
cSHAKE256(customization, input), producing DIGEST_LEN bytes.
hmac
KMAC256(key, customization, input), producing DIGEST_LEN bytes.
kdf
KMAC256-based KDF(key_material, customization), producing N bytes.
shake256
SHAKE256(input), producing DIGEST_LEN bytes.