1pub trait Modulus {
5 const Q: u32;
7
8 const N: usize;
10
11 const BARRETT_MU: u128 = 0;
14
15 const BARRETT_K: u32 = 0;
18}
19
20#[derive(Copy, Clone, Debug, Eq, PartialEq)]
26pub enum PostInvNtt {
27 Standard,
30 Montgomery,
33}
34
35pub trait NttModulus: Modulus {
37 const ZETA: u32;
39
40 const ZETAS: &'static [u32];
45
46 const N_INV: u32;
49
50 const MONT_R: u32;
52
53 const NEG_QINV: u32;
55
56 const PSIS: &'static [u32];
61
62 const INV_PSIS: &'static [u32];
66
67 const POST_INVNTT_MODE: PostInvNtt = PostInvNtt::Standard;
72}
73
74#[derive(Clone, Debug)]
76pub struct MlDsa44Params;
77
78impl Modulus for MlDsa44Params {
79 const Q: u32 = 8380417; const N: usize = 256;
81
82 const BARRETT_MU: u128 = 4_299_165_187;
86 const BARRETT_K: u32 = 55;
87}
88
89const ML_DSA_ZETAS: [u32; 255] = [
110 25847, 5771523, 7861508, 237124, 7602457, 7504169, 466468, 1826347, 2353451, 8021166, 6288512,
111 3119733, 5495562, 3111497, 2680103, 2725464, 1024112, 7300517, 3585928, 7830929, 7260833,
112 2619752, 6271868, 6262231, 4520680, 6980856, 5102745, 1757237, 8360995, 4010497, 280005,
113 2706023, 95776, 3077325, 3530437, 6718724, 4788269, 5842901, 3915439, 4519302, 5336701,
114 3574422, 5512770, 3539968, 8079950, 2348700, 7841118, 6681150, 6736599, 3505694, 4558682,
115 3507263, 6239768, 6779997, 3699596, 811944, 531354, 954230, 3881043, 3900724, 5823537, 2071892,
116 5582638, 4450022, 6851714, 4702672, 5339162, 6927966, 3475950, 2176455, 6795196, 7122806,
117 1939314, 4296819, 7380215, 5190273, 5223087, 4747489, 126922, 3412210, 7396998, 2147896,
118 2715295, 5412772, 4686924, 7969390, 5903370, 7709315, 7151892, 8357436, 7072248, 7998430,
119 1349076, 1852771, 6949987, 5037034, 264944, 508951, 3097992, 44288, 7280319, 904516, 3958618,
120 4656075, 8371839, 1653064, 5130689, 2389356, 8169440, 759969, 7063561, 189548, 4827145,
121 3159746, 6529015, 5971092, 8202977, 1315589, 1341330, 1285669, 6795489, 7567685, 6940675,
122 5361315, 4499357, 4751448, 3839961, 2091667, 3407706, 2316500, 3817976, 5037939, 2244091,
123 5933984, 4817955, 266997, 2434439, 7144689, 3513181, 4860065, 4621053, 7183191, 5187039,
124 900702, 1859098, 909542, 819034, 495491, 6767243, 8337157, 7857917, 7725090, 5257975, 2031748,
125 3207046, 4823422, 7855319, 7611795, 4784579, 342297, 286988, 5942594, 4108315, 3437287,
126 5038140, 1735879, 203044, 2842341, 2691481, 5790267, 1265009, 4055324, 1247620, 2486353,
127 1595974, 4613401, 1250494, 2635921, 4832145, 5386378, 1869119, 1903435, 7329447, 7047359,
128 1237275, 5062207, 6950192, 7929317, 1312455, 3306115, 6417775, 7100756, 1917081, 5834105,
129 7005614, 1500165, 777191, 2235880, 3406031, 7838005, 5548557, 6709241, 6533464, 5796124,
130 4656147, 594136, 4603424, 6366809, 2432395, 2454455, 8215696, 1957272, 3369112, 185531,
131 7173032, 5196991, 162844, 1616392, 3014001, 810149, 1652634, 4686184, 6581310, 5341501,
132 3523897, 3866901, 269760, 2213111, 7404533, 1717735, 472078, 7953734, 1723600, 6577327,
133 1910376, 6712985, 7276084, 8119771, 4546524, 5441381, 6144432, 7959518, 6094090, 183443,
134 7403526, 1612842, 4834730, 7826001, 3919660, 8332111, 7018208, 3937738, 1400424, 7534263,
135 1976782,
136];
137
138const ML_DSA_PSIS: [u32; 256] = [
142 1, 4808194, 3765607, 3761513, 5178923, 5496691, 5234739, 5178987, 7778734, 3542485, 2682288,
143 2129892, 3764867, 7375178, 557458, 7159240, 5010068, 4317364, 2663378, 6705802, 4855975,
144 7946292, 676590, 7044481, 5152541, 1714295, 2453983, 1460718, 7737789, 4795319, 2815639,
145 2283733, 3602218, 3182878, 2740543, 4793971, 5269599, 2101410, 3704823, 1159875, 394148,
146 928749, 1095468, 4874037, 2071829, 4361428, 3241972, 2156050, 3415069, 1759347, 7562881,
147 4805951, 3756790, 6444618, 6663429, 4430364, 5483103, 3192354, 556856, 3870317, 2917338,
148 1853806, 3345963, 1858416, 3073009, 1277625, 5744944, 3852015, 4183372, 5157610, 5258977,
149 8106357, 2508980, 2028118, 1937570, 4564692, 2811291, 5396636, 7270901, 4158088, 1528066,
150 482649, 1148858, 5418153, 7814814, 169688, 2462444, 5046034, 4213992, 4892034, 1987814,
151 5183169, 1736313, 235407, 5130263, 3258457, 5801164, 1787943, 5989328, 6125690, 3482206,
152 4197502, 7080401, 6018354, 7062739, 2461387, 3035980, 621164, 3901472, 7153756, 2925816,
153 3374250, 1356448, 5604662, 2683270, 5601629, 4912752, 2312838, 7727142, 7921254, 348812,
154 8052569, 1011223, 6026202, 4561790, 6458164, 6143691, 1744507, 1753, 6444997, 5720892, 6924527,
155 2660408, 6600190, 8321269, 2772600, 1182243, 87208, 636927, 4415111, 4423672, 6084020, 5095502,
156 4663471, 8352605, 822541, 1009365, 5926272, 6400920, 1596822, 4423473, 4620952, 6695264,
157 4969849, 2678278, 4611469, 4829411, 635956, 8129971, 5925040, 4234153, 6607829, 2192938,
158 6653329, 2387513, 4768667, 8111961, 5199961, 3747250, 2296099, 1239911, 4541938, 3195676,
159 2642980, 1254190, 8368000, 2998219, 141835, 8291116, 2513018, 7025515, 613238, 7070156,
160 6161950, 7921677, 6458423, 4040196, 4908348, 2039144, 6500539, 7561656, 6201452, 6757063,
161 2105286, 6006015, 6346610, 586241, 7200804, 527981, 5637006, 6903432, 1994046, 2491325,
162 6987258, 507927, 7192532, 7655613, 6545891, 5346675, 8041997, 2647994, 3009748, 5767564,
163 4148469, 749577, 4357667, 3980599, 2569011, 6764887, 1723229, 1665318, 2028038, 1163598,
164 5011144, 3994671, 8368538, 7009900, 3020393, 3363542, 214880, 545376, 7609976, 3105558,
165 7277073, 508145, 7826699, 860144, 3430436, 140244, 6866265, 6195333, 3123762, 2358373, 6187330,
166 5365997, 6663603, 2926054, 7987710, 8077412, 3531229, 4405932, 4606686, 1900052, 7598542,
167 1054478, 7648983,
168];
169
170const ML_DSA_INV_PSIS: [u32; 256] = [
173 1, 3572223, 4618904, 4614810, 3201430, 3145678, 2883726, 3201494, 1221177, 7822959, 1005239,
174 4615550, 6250525, 5698129, 4837932, 601683, 6096684, 5564778, 3585098, 642628, 6919699,
175 5926434, 6666122, 3227876, 1335936, 7703827, 434125, 3524442, 1674615, 5717039, 4063053,
176 3370349, 6522001, 5034454, 6526611, 5463079, 4510100, 7823561, 5188063, 2897314, 3950053,
177 1716988, 1935799, 4623627, 3574466, 817536, 6621070, 4965348, 6224367, 5138445, 4018989,
178 6308588, 3506380, 7284949, 7451668, 7986269, 7220542, 4675594, 6279007, 3110818, 3586446,
179 5639874, 5197539, 4778199, 6635910, 2236726, 1922253, 3818627, 2354215, 7369194, 327848,
180 8031605, 459163, 653275, 6067579, 3467665, 2778788, 5697147, 2775755, 7023969, 5006167,
181 5454601, 1226661, 4478945, 7759253, 5344437, 5919030, 1317678, 2362063, 1300016, 4182915,
182 4898211, 2254727, 2391089, 6592474, 2579253, 5121960, 3250154, 8145010, 6644104, 3197248,
183 6392603, 3488383, 4166425, 3334383, 5917973, 8210729, 565603, 2962264, 7231559, 7897768,
184 6852351, 4222329, 1109516, 2983781, 5569126, 3815725, 6442847, 6352299, 5871437, 274060,
185 3121440, 3222807, 4197045, 4528402, 2635473, 7102792, 5307408, 731434, 7325939, 781875,
186 6480365, 3773731, 3974485, 4849188, 303005, 392707, 5454363, 1716814, 3014420, 2193087,
187 6022044, 5256655, 2185084, 1514152, 8240173, 4949981, 7520273, 553718, 7872272, 1103344,
188 5274859, 770441, 7835041, 8165537, 5016875, 5360024, 1370517, 11879, 4385746, 3369273, 7216819,
189 6352379, 6715099, 6657188, 1615530, 5811406, 4399818, 4022750, 7630840, 4231948, 2612853,
190 5370669, 5732423, 338420, 3033742, 1834526, 724804, 1187885, 7872490, 1393159, 5889092,
191 6386371, 1476985, 2743411, 7852436, 1179613, 7794176, 2033807, 2374402, 6275131, 1623354,
192 2178965, 818761, 1879878, 6341273, 3472069, 4340221, 1921994, 458740, 2218467, 1310261,
193 7767179, 1354892, 5867399, 89301, 8238582, 5382198, 12417, 7126227, 5737437, 5184741, 3838479,
194 7140506, 6084318, 4633167, 3180456, 268456, 3611750, 5992904, 1727088, 6187479, 1772588,
195 4146264, 2455377, 250446, 7744461, 3551006, 3768948, 5702139, 3410568, 1685153, 3759465,
196 3956944, 6783595, 1979497, 2454145, 7371052, 7557876, 27812, 3716946, 3284915, 2296397,
197 3956745, 3965306, 7743490, 8293209, 7198174, 5607817, 59148, 1780227, 5720009, 1455890,
198 2659525, 1935420, 8378664,
199];
200
201#[derive(Clone, Debug)]
203pub struct MlDsaParams;
204
205impl Modulus for MlDsaParams {
206 const Q: u32 = 8380417; const N: usize = 256;
208
209 const BARRETT_MU: u128 = 4_299_165_187;
213 const BARRETT_K: u32 = 55;
214}
215
216impl NttModulus for MlDsaParams {
217 const ZETA: u32 = 1753; const ZETAS: &'static [u32] = &ML_DSA_ZETAS;
223
224 const N_INV: u32 = 16_382;
229
230 const MONT_R: u32 = 4_193_792;
232
233 const NEG_QINV: u32 = 4_236_238_847;
237
238 const PSIS: &'static [u32] = &ML_DSA_PSIS;
240 const INV_PSIS: &'static [u32] = &ML_DSA_INV_PSIS;
241
242 const POST_INVNTT_MODE: PostInvNtt = PostInvNtt::Standard;
244}
245
246#[derive(Clone, Debug)]
249pub struct MlDsaParamsMont;
250
251impl Modulus for MlDsaParamsMont {
252 const Q: u32 = 8380417;
253 const N: usize = 256;
254 const BARRETT_MU: u128 = 4_299_165_187;
255 const BARRETT_K: u32 = 55;
256}
257
258impl NttModulus for MlDsaParamsMont {
259 const ZETA: u32 = 1753;
260 const ZETAS: &'static [u32] = &ML_DSA_ZETAS;
261 const N_INV: u32 = 16_382;
262 const MONT_R: u32 = 4_193_792;
263 const NEG_QINV: u32 = 4_236_238_847;
264 const PSIS: &'static [u32] = &ML_DSA_PSIS;
265 const INV_PSIS: &'static [u32] = &ML_DSA_INV_PSIS;
266
267 const POST_INVNTT_MODE: PostInvNtt = PostInvNtt::Montgomery;
269}
270
271pub fn is_prime(q: u32) -> bool {
274 if q < 2 {
275 return false;
276 }
277 if q == 2 {
278 return true;
279 }
280 if q % 2 == 0 {
281 return false;
282 }
283
284 let mut i = 3u32;
285 while i <= q / i {
286 if q % i == 0 {
287 return false;
288 }
289 i += 2;
290 }
291 true
292}
293
294pub fn is_power_of_two(n: usize) -> bool {
296 n > 0 && (n & (n - 1)) == 0
297}
298
299#[cfg(test)]
300mod tests {
301 use super::*;
302
303 #[test]
304 fn test_ml_dsa_params() {
305 assert_eq!(MlDsa44Params::Q, 8380417);
306 assert_eq!(MlDsa44Params::N, 256);
307 assert!(is_prime(MlDsa44Params::Q));
308 assert_eq!(MlDsa44Params::BARRETT_MU, 4_299_165_187);
309 assert_eq!(MlDsa44Params::BARRETT_K, 55);
310 }
311
312 #[test]
313 fn test_ml_dsa_general_params() {
314 assert_eq!(MlDsaParams::Q, 8380417);
315 assert_eq!(MlDsaParams::N, 256);
316 assert!(is_prime(MlDsaParams::Q));
317 assert!(is_power_of_two(MlDsaParams::N));
318 assert_eq!(MlDsaParams::POST_INVNTT_MODE, PostInvNtt::Standard);
320 assert_eq!(MlDsaParams::BARRETT_MU, 4_299_165_187);
321 assert_eq!(MlDsaParams::BARRETT_K, 55);
322 }
323
324 #[test]
325 fn test_ml_dsa_constant_calculations() {
326 let n_inv_std = 8_347_681u64; let r = MlDsaParams::MONT_R as u64;
332 let q = MlDsaParams::Q as u64;
333 let expected_n_inv = (n_inv_std * r) % q;
334 assert_eq!(expected_n_inv, 16_382);
335 assert_eq!(MlDsaParams::N_INV as u64, expected_n_inv);
336
337 let q_inv: u32 = 58728449; let neg_qinv = (1u64 << 32) - (q_inv as u64);
342 assert_eq!(neg_qinv, 4_236_238_847);
343 assert_eq!(MlDsaParams::NEG_QINV as u64, neg_qinv);
344 }
345
346 #[test]
347 fn test_zetas_in_montgomery_domain() {
348 assert_eq!(MlDsaParams::ZETAS[0], 25_847);
351
352 let zeta_128_std = 4808194u64; let mont_form = (zeta_128_std * MlDsaParams::MONT_R as u64) % MlDsaParams::Q as u64;
355 assert_eq!(mont_form as u32, 25_847);
356 }
357
358 #[test]
359 fn test_twist_factors() {
360 assert_eq!(MlDsaParams::PSIS.len(), 256);
362 assert_eq!(MlDsaParams::INV_PSIS.len(), 256);
363
364 assert_eq!(MlDsaParams::PSIS[0], 1);
366 assert_eq!(MlDsaParams::INV_PSIS[0], 1);
367
368 let q = MlDsaParams::Q as u64;
370 for i in 0..10 {
371 let psi = MlDsaParams::PSIS[i] as u64;
372 let inv_psi = MlDsaParams::INV_PSIS[i] as u64;
373 let product = (psi * inv_psi) % q;
374 assert_eq!(product, 1, "ψ[{}] * ψ^(-1)[{}] should equal 1", i, i);
375 }
376 }
377}