Skip to main content

quantica/slh_dsa/
params.rs

1//! SLH-DSA parameter sets (FIPS 205, Section 11).
2//!
3//! This module defines the [`Params`] trait and the six SHAKE-based parameter set structs.
4//! All SHAKE-based parameter sets use Winternitz parameter `w = 16` (`lg_w = 4`).
5//!
6//! Each parameter set is identified by its security level (128, 192, or 256 bits) and
7//! a size/speed trade-off suffix: "s" (small signatures) or "f" (fast signing/verification).
8
9/// Trait defining all compile-time parameters for an SLH-DSA instance.
10///
11/// Implementors of this trait represent a specific FIPS 205 parameter set (e.g.,
12/// SLH-DSA-SHAKE-128f). The constants fully determine key sizes, signature sizes,
13/// tree structures, and hash output lengths.
14///
15/// See FIPS 205, Table 2 for the complete list of parameter values.
16pub trait Params: Clone + Default {
17    /// Security parameter `n`: hash output length in bytes.
18    ///
19    /// This is the fundamental security parameter. All hash outputs, secret values,
20    /// and tree nodes are `n` bytes long.
21    const N: usize;
22    /// Total hypertree height: `h = d * h'`.
23    ///
24    /// Determines the total number of FORS key pairs the scheme can use: `2^h`.
25    const H: usize;
26    /// Number of layers `d` in the hypertree.
27    ///
28    /// The hypertree consists of `d` stacked XMSS trees, each of height `h'`.
29    const D: usize;
30    /// Height `h'` of each individual XMSS tree within the hypertree.
31    ///
32    /// Each XMSS tree authenticates `2^h'` keys in the layer below it.
33    const H_PRIME: usize;
34    /// Height `a` of each FORS tree (each tree has `2^a` leaves).
35    const A: usize;
36    /// Number `k` of FORS trees used per signature.
37    const K: usize;
38    /// Winternitz parameter `lg(w)`, always 4 for SHAKE-based parameter sets.
39    const LG_W: usize = 4;
40    /// Winternitz parameter `w = 2^lg_w = 16`.
41    ///
42    /// Controls the time/size trade-off in WOTS+ chains: each chain has `w - 1` steps.
43    const W: usize = 16;
44    /// Message digest length `m` in bytes, output by `H_msg`.
45    ///
46    /// The digest is split into FORS indices, a tree index, and a leaf index.
47    const M: usize;
48
49    // Derived WOTS+ constants
50    /// WOTS+ parameter `len1 = ceil(8*n / lg_w) = 2*n` (since `lg_w = 4`).
51    ///
52    /// Number of base-`w` digits needed to represent an `n`-byte message.
53    const LEN1: usize = 2 * Self::N;
54    /// WOTS+ parameter `len2 = 3` for all SHAKE-based parameter sets.
55    ///
56    /// Number of base-`w` digits in the checksum.
57    const LEN2: usize = 3;
58    /// WOTS+ parameter `len = len1 + len2`: total number of hash chains.
59    const LEN: usize = Self::LEN1 + Self::LEN2;
60
61    // Key and signature sizes
62    /// Public key size in bytes: `2*n` (PK.seed || PK.root).
63    const PK_LEN: usize = 2 * Self::N;
64    /// Secret key size in bytes: `4*n` (SK.seed || SK.prf || PK.seed || PK.root).
65    const SK_LEN: usize = 4 * Self::N;
66
67    /// Human-readable name of this parameter set (e.g., `"SLH-DSA-SHAKE-128f"`).
68    const NAME: &'static str;
69}
70
71/// Compute the total SLH-DSA signature length in bytes for parameter set `P`.
72///
73/// The signature layout is `R || SIG_FORS || SIG_HT`, with total size:
74/// `n + k*(1+a)*n + (h + d*len)*n`.
75///
76/// This is a runtime function rather than a `const` due to Rust const-generics limitations.
77pub fn sig_len<P: Params>() -> usize {
78    // R || SIG_FORS || SIG_HT
79    // n + k*(1+a)*n + (h + d*len)*n
80    P::N + P::K * (1 + P::A) * P::N + (P::H + P::D * P::LEN) * P::N
81}
82
83// ====== SHAKE-128s ======
84/// SLH-DSA-SHAKE-128s parameter set (NIST security level 1, small signatures).
85///
86/// Provides 128-bit security with relatively compact signatures (~7856 bytes) but
87/// slower signing and verification compared to [`Shake128f`].
88#[derive(Clone, Default)]
89pub struct Shake128s;
90
91impl Params for Shake128s {
92    const N: usize = 16;
93    const H: usize = 63;
94    const D: usize = 7;
95    const H_PRIME: usize = 9;
96    const A: usize = 12;
97    const K: usize = 14;
98    const M: usize = 30;
99    const NAME: &'static str = "SLH-DSA-SHAKE-128s";
100}
101
102// ====== SHAKE-128f ======
103/// SLH-DSA-SHAKE-128f parameter set (NIST security level 1, fast operations).
104///
105/// Provides 128-bit security with faster signing and verification but larger
106/// signatures (~17088 bytes) compared to [`Shake128s`].
107#[derive(Clone, Default)]
108pub struct Shake128f;
109
110impl Params for Shake128f {
111    const N: usize = 16;
112    const H: usize = 66;
113    const D: usize = 22;
114    const H_PRIME: usize = 3;
115    const A: usize = 6;
116    const K: usize = 33;
117    const M: usize = 34;
118    const NAME: &'static str = "SLH-DSA-SHAKE-128f";
119}
120
121// ====== SHAKE-192s ======
122/// SLH-DSA-SHAKE-192s parameter set (NIST security level 3, small signatures).
123///
124/// Provides 192-bit security with compact signatures but slower operations
125/// compared to [`Shake192f`].
126#[derive(Clone, Default)]
127pub struct Shake192s;
128
129impl Params for Shake192s {
130    const N: usize = 24;
131    const H: usize = 63;
132    const D: usize = 7;
133    const H_PRIME: usize = 9;
134    const A: usize = 14;
135    const K: usize = 17;
136    const M: usize = 39;
137    const NAME: &'static str = "SLH-DSA-SHAKE-192s";
138}
139
140// ====== SHAKE-192f ======
141/// SLH-DSA-SHAKE-192f parameter set (NIST security level 3, fast operations).
142///
143/// Provides 192-bit security with faster signing and verification but larger
144/// signatures compared to [`Shake192s`].
145#[derive(Clone, Default)]
146pub struct Shake192f;
147
148impl Params for Shake192f {
149    const N: usize = 24;
150    const H: usize = 66;
151    const D: usize = 22;
152    const H_PRIME: usize = 3;
153    const A: usize = 8;
154    const K: usize = 33;
155    const M: usize = 42;
156    const NAME: &'static str = "SLH-DSA-SHAKE-192f";
157}
158
159// ====== SHAKE-256s ======
160/// SLH-DSA-SHAKE-256s parameter set (NIST security level 5, small signatures).
161///
162/// Provides 256-bit security with compact signatures but slower operations
163/// compared to [`Shake256f`].
164#[derive(Clone, Default)]
165pub struct Shake256s;
166
167impl Params for Shake256s {
168    const N: usize = 32;
169    const H: usize = 64;
170    const D: usize = 8;
171    const H_PRIME: usize = 8;
172    const A: usize = 14;
173    const K: usize = 22;
174    const M: usize = 47;
175    const NAME: &'static str = "SLH-DSA-SHAKE-256s";
176}
177
178// ====== SHAKE-256f ======
179/// SLH-DSA-SHAKE-256f parameter set (NIST security level 5, fast operations).
180///
181/// Provides 256-bit security with faster signing and verification but larger
182/// signatures compared to [`Shake256s`].
183#[derive(Clone, Default)]
184pub struct Shake256f;
185
186impl Params for Shake256f {
187    const N: usize = 32;
188    const H: usize = 68;
189    const D: usize = 17;
190    const H_PRIME: usize = 4;
191    const A: usize = 9;
192    const K: usize = 35;
193    const M: usize = 49;
194    const NAME: &'static str = "SLH-DSA-SHAKE-256f";
195}