quantica/ml_dsa/params.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Cédric Mesnil <cslashm@pm.me>
3
4//! ML-DSA parameter sets (FIPS 204, Table 1).
5//!
6//! Defines the global constants shared across all parameter sets (the prime
7//! modulus `Q`, polynomial degree `N`, etc.) and the [`Params`] trait that
8//! encodes the per-security-level constants.
9
10/// The prime modulus q = 2^23 - 2^13 + 1 = 8380417.
11///
12/// All polynomial arithmetic in ML-DSA is performed modulo this prime.
13pub const Q: i32 = 8380417;
14
15/// Polynomial degree (number of coefficients per polynomial).
16///
17/// ML-DSA operates over the ring `Z_q[X]/(X^256 + 1)`.
18pub const N: usize = 256;
19
20/// Primitive 512th root of unity modulo q.
21///
22/// Used to build the NTT twiddle factor table. zeta = 1753 satisfies
23/// zeta^256 = -1 (mod q).
24pub const ZETA: i32 = 1753;
25
26/// Maximum value of K across all parameter sets (ML-DSA-87 has K=8).
27pub const MAX_K: usize = 8;
28
29/// Maximum value of L across all parameter sets (ML-DSA-87 has L=7).
30pub const MAX_L: usize = 7;
31
32/// The `d` parameter (number of dropped bits from t).
33///
34/// Public key compression drops the low `d = 13` bits of the vector t,
35/// splitting it into (t1, t0) via Power2Round.
36pub const D: usize = 13;
37
38/// Multiplicative inverse of N modulo q: 256^{-1} mod q.
39///
40/// Applied as a final scaling factor in the inverse NTT.
41pub const N_INV: i32 = 8347681;
42
43/// Parameter trait for ML-DSA security levels.
44///
45/// Each implementor (e.g., [`MlDsa44`], [`MlDsa65`], [`MlDsa87`]) provides
46/// the constants from FIPS 204, Table 1. Derived sizes for public key,
47/// secret key, and signature are computed automatically from the base
48/// constants.
49pub trait Params {
50 /// Number of rows in the matrix A (dimension k).
51 const K: usize;
52 /// Number of columns in the matrix A (dimension l).
53 const L: usize;
54 /// Secret key coefficient bound: coefficients of s1, s2 lie in [-eta, eta].
55 const ETA: usize;
56 /// Number of +/-1 entries in the challenge polynomial c.
57 const TAU: usize;
58 /// Signing bound beta = tau * eta. Candidate signatures with infinity norm >= gamma1 - beta are rejected.
59 const BETA: i32;
60 /// Masking range: coefficients of the masking vector y are sampled from [-(gamma1-1), gamma1].
61 const GAMMA1: i32;
62 /// Decomposition parameter: controls the rounding used in HighBits/LowBits.
63 const GAMMA2: i32;
64 /// Maximum number of non-zero hint entries allowed across all k hint polynomials.
65 const OMEGA: usize;
66 /// Collision strength in bits; determines the length of the commitment hash c_tilde (lambda/4 bytes).
67 const LAMBDA: usize;
68
69 /// Public key length in bytes: 32 (rho) + k * 320 (encoded t1).
70 const PK_LEN: usize = 32 + 32 * Self::K * 10; // bitlen(q-1)-d = 23-13 = 10
71 /// Secret key length in bytes.
72 const SK_LEN: usize = 32 + 32 + 64 + 32 * (Self::L + Self::K) * Self::BITLEN_2ETA + 32 * Self::K * D;
73 /// Signature length in bytes.
74 const SIG_LEN: usize = Self::LAMBDA / 4 + Self::L * 32 * (1 + Self::BITLEN_GAMMA1_MINUS1) + Self::OMEGA + Self::K;
75
76 /// Helper constant: bit-length of 2*eta, used for encoding secret polynomials.
77 const BITLEN_2ETA: usize;
78 /// Helper constant: bit-length of gamma1 - 1, used for encoding z in signatures.
79 const BITLEN_GAMMA1_MINUS1: usize;
80}
81
82/// ML-DSA-44 parameter set (NIST security level 2).
83///
84/// Provides approximately 128 bits of classical security. Matrix dimensions
85/// are k=4, l=4 with eta=2.
86pub struct MlDsa44;
87
88impl Params for MlDsa44 {
89 const K: usize = 4;
90 const L: usize = 4;
91 const ETA: usize = 2;
92 const TAU: usize = 39;
93 const BETA: i32 = 78;
94 const GAMMA1: i32 = 1 << 17; // 2^17
95 const GAMMA2: i32 = (Q - 1) / 88; // 95232
96 const OMEGA: usize = 80;
97 const LAMBDA: usize = 128;
98 const BITLEN_2ETA: usize = 3; // bitlen(4) = 3
99 const BITLEN_GAMMA1_MINUS1: usize = 17; // bitlen(2^17 - 1) = 17
100}
101
102/// ML-DSA-65 parameter set (NIST security level 3).
103///
104/// Provides approximately 192 bits of classical security. Matrix dimensions
105/// are k=6, l=5 with eta=4.
106pub struct MlDsa65;
107
108impl Params for MlDsa65 {
109 const K: usize = 6;
110 const L: usize = 5;
111 const ETA: usize = 4;
112 const TAU: usize = 49;
113 const BETA: i32 = 196;
114 const GAMMA1: i32 = 1 << 19; // 2^19
115 const GAMMA2: i32 = (Q - 1) / 32; // 261888
116 const OMEGA: usize = 55;
117 const LAMBDA: usize = 192;
118 const BITLEN_2ETA: usize = 4; // bitlen(8) = 4
119 const BITLEN_GAMMA1_MINUS1: usize = 19; // bitlen(2^19 - 1) = 19
120}
121
122/// ML-DSA-87 parameter set (NIST security level 5).
123///
124/// Provides approximately 256 bits of classical security. Matrix dimensions
125/// are k=8, l=7 with eta=2.
126pub struct MlDsa87;
127
128impl Params for MlDsa87 {
129 const K: usize = 8;
130 const L: usize = 7;
131 const ETA: usize = 2;
132 const TAU: usize = 60;
133 const BETA: i32 = 120;
134 const GAMMA1: i32 = 1 << 19; // 2^19
135 const GAMMA2: i32 = (Q - 1) / 32; // 261888
136 const OMEGA: usize = 75;
137 const LAMBDA: usize = 256;
138 const BITLEN_2ETA: usize = 3; // bitlen(4) = 3
139 const BITLEN_GAMMA1_MINUS1: usize = 19; // bitlen(2^19 - 1) = 19
140}