Skip to main content

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}