1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//! # 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`](https://docs.rs/silentops)) used by the classical
//! side of the workspace ([`arcana`](https://docs.rs/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`](ml_kem::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
//!
//! ```no_run
//! 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>`](ml_kem::EncapsulationKey), [`Ciphertext<P>`](ml_kem::Ciphertext) | [`DecapsulationKey<P>`](ml_kem::DecapsulationKey), [`SharedSecret`](ml_kem::SharedSecret) |
//! | [`ml_dsa`] | [`VerifyingKey<P>`](ml_dsa::VerifyingKey), [`Signature<P>`](ml_dsa::Signature) | [`SigningKey<P>`](ml_dsa::SigningKey) |
//! | [`slh_dsa`]| [`VerifyingKey<P>`](slh_dsa::VerifyingKey), [`Signature<P>`](slh_dsa::Signature) | [`SigningKey<P>`](slh_dsa::SigningKey) |
//!
//! 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 `OsRng` is not available — callers must provide
//! their own [`CryptoRng`](ml_kem::CryptoRng) implementation
//! (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
//!
//! ```bash
//! 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_verify
//! ```
extern crate alloc;
// Bring `Vec` into scope for all submodules without forcing a per-file
// `use alloc::vec::Vec;`. The `vec!` macro is brought in via the
// `#[macro_use] extern crate alloc;` above.
pub use Vec;
// Shared Keccak-f[1600] core used by every algorithm. Crate-private:
// each algorithm exposes its own thin `sha3` wrapper module on top.
/// Zeroize-on-Drop wrappers for secret key material
/// ([`SecretBytes`](secret::SecretBytes), [`SecretArray`](secret::SecretArray)).