Expand description
§quantica — post-quantum cryptography for the krypteia workspace
Pure-Rust implementations of the three NIST post-quantum standards,
sharing the same side-channel countermeasure toolkit
(silentops) used by the classical
side of the workspace (arcana).
| Module | Standard | Algorithm | Validation |
|---|---|---|---|
ml_kem | FIPS 203 | ML-KEM (key encapsulation) | ACVP + Wycheproof |
ml_dsa | FIPS 204 | ML-DSA (digital signature) | ACVP + Wycheproof |
slh_dsa | FIPS 205 | SLH-DSA (hash-based digital signature) | ACVP (Wycheproof has no SLH-DSA corpus yet) |
§Cargo features
| Feature | Default | Effect |
|---|---|---|
std | on | Pulls in the standard library. Enables OsRng and std::error::Error impls. |
ml-kem | on | Compiles the FIPS 203 module (ml_kem). |
ml-dsa | on | Compiles the FIPS 204 module (ml_dsa). |
slh-dsa | on | Compiles the FIPS 205 module (slh_dsa). |
sca-protected | on | Activates the masking + shuffled-NTT defences inside ML-KEM and ML-DSA (see below). |
Disable std for no_std builds: pass --no-default-features
then re-enable the algorithms you need. The crate still requires
alloc (keys, ciphertexts and signatures are Vec<u8>-backed).
§Quick start
use quantica::ml_kem::*;
let mut rng = OsRng;
let (ek, dk) = MlKem::<MlKem768>::keygen(&mut rng).unwrap();
let (ss_a, ct) = MlKem::<MlKem768>::encaps(&ek, &mut rng).unwrap();
let ss_b = MlKem::<MlKem768>::decaps(&dk, &ct, &mut rng).unwrap();
assert_eq!(ss_a, ss_b);
// Both shared secrets auto-zeroize when they drop.§Typed key wrappers (Zeroize-on-Drop)
The public API never returns raw Vec<u8> for secret material.
Each algorithm exposes parameter-set-tagged wrapper types backed
by the shared secret module:
| Module | Public (not zeroized) | Secret (Drop-zeroizes) |
|---|---|---|
ml_kem | EncapsulationKey<P>, Ciphertext<P> | DecapsulationKey<P>, SharedSecret |
ml_dsa | VerifyingKey<P>, Signature<P> | SigningKey<P> |
slh_dsa | VerifyingKey<P>, Signature<P> | SigningKey<P> |
All wrappers implement from_bytes(&[u8]) (length-validated),
as_bytes(), Deref<Target=[u8]>, AsRef<[u8]> and Clone.
Secret variants have a redacted Debug impl
(<redacted; len=N>) so stray logging cannot leak key material.
The internal byte-slice API (ml_kem::kem::*, ml_dsa::dsa::*,
slh_dsa::slh::*) is still public for ACVP/CAVP testing and
for the C FFI.
§Side-channel countermeasures
§Always-on (every build)
| Defence | Algorithms | Threat addressed |
|---|---|---|
| Constant-time arith | all three | Timing / cache / basic SPA |
| Zeroize-on-Drop | all three | Cold boot, memory dumps, UAF |
| Volatile zeroization | all three | Same, on intermediates |
| Double Decaps | ML-KEM | DFA on FO comparison |
| dk integrity check | ML-KEM | DFA on stored key material |
| Hedged signing | ML-DSA, SLH-DSA | Fault-induced nonce reuse |
§sca-protected (on by default)
| Defence | Algorithms | Module |
|---|---|---|
| First-order additive masking | ML-KEM, ML-DSA | ml_kem::masked, ml_dsa::masked |
| Shuffled NTT (Fisher-Yates) | ML-KEM, ML-DSA | ml_kem::shuffle, ml_dsa::shuffle |
| Mask refresh between rounds | ML-DSA | MaskedPoly::refresh() per rejection iteration |
The masking layer is mathematically transparent: unmask(op(mask(s), public)) ≡ op(s, public).
All NIST ACVP vectors pass unchanged with sca-protected enabled — the masked path produces
bit-identical signatures and shared secrets.
SLH-DSA is purely hash-based and has no algebraic structure to mask; the always-on defences are the relevant layer there.
§no_std
quantica is std-by-default, but the standard library is gated
behind the std feature. Building with
--no-default-features --features ml-kem,ml-dsa,slh-dsa,sca-protected
produces a no_std crate that still depends on alloc (because
the algorithms allocate heap buffers for keys, ciphertexts and
signatures). In no_std mode:
- The OS-backed
OsRngis not available — callers must provide their ownCryptoRngimplementation (typically wrapping a hardware RNG on embedded targets). - The error enums no longer implement
std::error::Error.
Cross-compile validated on thumbv7em-none-eabihf (Cortex-M4),
thumbv6m-none-eabi (Cortex-M0), and riscv32imc-unknown-none-elf
(ESP32-C3) with all three algorithms + sca-protected enabled.
§Examples
cargo run --release -p quantica --example ml_kem_roundtrip
cargo run --release -p quantica --example ml_dsa_sign_verify
cargo run --release -p quantica --example slh_dsa_sign_verifyModules§
- ml_dsa
- ML-DSA: Module-Lattice-Based Digital Signature Standard (FIPS 204).
- ml_kem
- ML-KEM — Module-Lattice-Based Key-Encapsulation Mechanism
- secret
- Zeroize-on-Drop wrappers for secret key material
(
SecretBytes,SecretArray). Zeroize-on-Drop containers for secret key material. - slh_dsa
- SLH-DSA: Stateless Hash-Based Digital Signature Standard (FIPS 205).