Skip to content

Commit fd3dc5f

Browse files
MauroToscanoSergio Chouhy
andauthored
Montgomery autocalculate params (#118)
* Add const shift to calculate montgomery params * Add const rem by substractions * Add comments * Fix warnings * compute MP at compile time * compute R2 at compile time * rename mp to mu * fix typo * Re added mul comments --------- Co-authored-by: Sergio Chouhy <[email protected]>
1 parent 3aac102 commit fd3dc5f

File tree

7 files changed

+280
-88
lines changed

7 files changed

+280
-88
lines changed

crypto/src/hash/poseidon/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,6 @@ mod tests {
158158
impl IsMontgomeryConfiguration for TestFieldConfig {
159159
const MODULUS: U384 =
160160
U384::from("2000000000000080000000000000000000000000000000000000000000000001");
161-
const MP: u64 = 18446744073709551615u64;
162-
const R2: U384 =
163-
U384::from("C0000FFFFCFFFF800000000C0001FFFFFFFFBFFFF80000000140001FFFFE00");
164161
}
165162

166163
pub type PoseidonTestField = MontgomeryBackendPrimeField<TestFieldConfig>;

math/src/elliptic_curve/short_weierstrass/curves/bls12_377/field_extension.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ pub const BLS12377_PRIME_FIELD_ORDER: U384 = U384::from("1ae3a4617c510eac63b05c0
1111
pub struct BLS12377FieldConfig;
1212
impl IsMontgomeryConfiguration for BLS12377FieldConfig {
1313
const MODULUS: U384 = BLS12377_PRIME_FIELD_ORDER;
14-
const MP: u64 = 9586122913090633727;
15-
const R2: U384 = U384::from("6dfccb1e914b88837e92f041790bf9bfdf7d03827dc3ac22a5f11162d6b46d0329fcaab00431b1b786686c9400cd22");
1614
}
1715

1816
pub type BLS12377PrimeField = MontgomeryBackendPrimeField<BLS12377FieldConfig>;

math/src/elliptic_curve/short_weierstrass/curves/bls12_381/field_extension.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ pub const BLS12381_PRIME_FIELD_ORDER: U384 = U384::from("1a0111ea397fe69a4b1ba7b
1515
pub struct BLS12381FieldConfig;
1616
impl IsMontgomeryConfiguration for BLS12381FieldConfig {
1717
const MODULUS: U384 = BLS12381_PRIME_FIELD_ORDER;
18-
const MP: u64 = 9940570264628428797;
19-
const R2: U384 = U384::from("11988fe592cae3aa9a793e85b519952d67eb88a9939d83c08de5476c4c95b6d50a76e6a609d104f1f4df1f341c341746");
2018
}
2119

2220
pub type BLS12381PrimeField = MontgomeryBackendPrimeField<BLS12381FieldConfig>;

math/src/elliptic_curve/short_weierstrass/curves/test_curve_2.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ pub const TEST_CURVE_2_MAIN_SUBGROUP_ORDER: U384 = U384::from("40a065fb5a76390de
2323
pub struct TestCurve2MontgomeryConfig;
2424
impl IsMontgomeryConfiguration for TestCurve2MontgomeryConfig {
2525
const MODULUS: U384 = TEST_CURVE_2_PRIME_FIELD_ORDER;
26-
const MP: u64 = 1901108026836139985;
27-
const R2: U384 = U384::from("f60e53d42ca85ba186067660c4f2daa94");
2826
}
2927

3028
type TestCurve2PrimeField = MontgomeryBackendPrimeField<TestCurve2MontgomeryConfig>;

math/src/field/fields/u384_prime_field.rs

Lines changed: 155 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,68 @@ use crate::{
55
field::traits::IsField, unsigned_integer::element::UnsignedInteger,
66
unsigned_integer::montgomery::MontgomeryAlgorithms,
77
};
8+
89
use std::fmt::Debug;
910
use std::marker::PhantomData;
1011

12+
/// Computes `- modulus^{-1} mod 2^{64}`
13+
/// This algorithm is given by Dussé and Kaliski Jr. in
14+
/// "S. R. Dussé and B. S. Kaliski Jr. A cryptographic library for the Motorola
15+
/// DSP56000. In I. Damgård, editor, Advances in Cryptology – EUROCRYPT’90,
16+
/// volume 473 of Lecture Notes in Computer Science, pages 230–244. Springer,
17+
/// Heidelberg, May 1991."
18+
const fn compute_mu_parameter(modulus: &U384) -> u64 {
19+
let mut y = 1;
20+
let word_size = 64;
21+
let mut i: usize = 2;
22+
while i <= word_size {
23+
let (_, lo) = U384::mul(modulus, &U384::from_u64(y));
24+
let least_significant_limb = lo.limbs[5];
25+
if (least_significant_limb << (word_size - i)) >> (word_size - i) != 1 {
26+
y += 1 << (i - 1);
27+
}
28+
i += 1;
29+
}
30+
y.wrapping_neg()
31+
}
32+
33+
/// Computes 2^{384 * 2} modulo `modulus`
34+
const fn compute_r2_parameter(modulus: &U384) -> U384 {
35+
let number_limbs = 6;
36+
let word_size = 64;
37+
let mut l: usize = 0;
38+
let zero = U384::from_u64(0);
39+
// Define `c` as the largest power of 2 smaller than `modulus`
40+
while l < number_limbs * word_size {
41+
if U384::const_ne(&modulus.const_shr(l), &zero) {
42+
break;
43+
}
44+
l += 1;
45+
}
46+
let mut c = U384::from_u64(1).const_shl(l);
47+
48+
// Double `c` and reduce modulo `modulus` until getting
49+
// `2^{2 * number_limbs * word_size}` mod `modulus`
50+
let mut i: usize = 1;
51+
while i <= 2 * number_limbs * word_size - l {
52+
let (double_c, overflow) = U384::add(&c, &c);
53+
c = if U384::const_le(modulus, &double_c) || overflow {
54+
U384::sub(&double_c, modulus).0
55+
} else {
56+
double_c
57+
};
58+
i += 1;
59+
}
60+
c
61+
}
62+
1163
/// This trait is necessary for us to be able to use unsigned integer types bigger than
1264
/// `u128` (the biggest native `unit`) as constant generics.
1365
/// This trait should be removed when Rust supports this feature.
1466
pub trait IsMontgomeryConfiguration {
1567
const MODULUS: U384;
16-
const R2: U384;
17-
const MP: u64;
68+
const R2: U384 = compute_r2_parameter(&Self::MODULUS);
69+
const MU: u64 = compute_mu_parameter(&Self::MODULUS);
1870
}
1971

2072
#[derive(Clone, Debug)]
@@ -50,7 +102,7 @@ where
50102
}
51103

52104
fn mul(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
53-
MontgomeryAlgorithms::cios(a, b, &C::MODULUS, &C::MP)
105+
MontgomeryAlgorithms::cios(a, b, &C::MODULUS, &C::MU)
54106
}
55107

56108
fn sub(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
@@ -93,11 +145,11 @@ where
93145
}
94146

95147
fn from_u64(x: u64) -> Self::BaseType {
96-
MontgomeryAlgorithms::cios(&UnsignedInteger::from_u64(x), &C::R2, &C::MODULUS, &C::MP)
148+
MontgomeryAlgorithms::cios(&UnsignedInteger::from_u64(x), &C::R2, &C::MODULUS, &C::MU)
97149
}
98150

99151
fn from_base_type(x: Self::BaseType) -> Self::BaseType {
100-
MontgomeryAlgorithms::cios(&x, &C::R2, &C::MODULUS, &C::MP)
152+
MontgomeryAlgorithms::cios(&x, &C::R2, &C::MODULUS, &C::MU)
101153
}
102154
}
103155

@@ -106,12 +158,12 @@ where
106158
C: IsMontgomeryConfiguration + Clone + Debug,
107159
{
108160
fn to_bytes_be(&self) -> Vec<u8> {
109-
MontgomeryAlgorithms::cios(self.value(), &U384::from_u64(1), &C::MODULUS, &C::MP)
161+
MontgomeryAlgorithms::cios(self.value(), &U384::from_u64(1), &C::MODULUS, &C::MU)
110162
.to_bytes_be()
111163
}
112164

113165
fn to_bytes_le(&self) -> Vec<u8> {
114-
MontgomeryAlgorithms::cios(self.value(), &U384::from_u64(1), &C::MODULUS, &C::MP)
166+
MontgomeryAlgorithms::cios(self.value(), &U384::from_u64(1), &C::MODULUS, &C::MU)
115167
.to_bytes_le()
116168
}
117169

@@ -129,20 +181,113 @@ where
129181
#[cfg(test)]
130182
mod tests {
131183
use crate::{
132-
field::element::FieldElement,
184+
field::{
185+
element::FieldElement,
186+
fields::u384_prime_field::{compute_mu_parameter, compute_r2_parameter},
187+
},
133188
traits::ByteConversion,
134189
unsigned_integer::element::{UnsignedInteger, U384},
135190
};
136191

137192
use super::{IsMontgomeryConfiguration, MontgomeryBackendPrimeField};
138193

194+
#[test]
195+
fn test_compute_mu_parameter_1() {
196+
let modulus = U384 {
197+
limbs: [0, 0, 0, 0, 0, 23],
198+
};
199+
let mu = compute_mu_parameter(&modulus);
200+
let expected_mu: u64 = 3208129404123400281;
201+
assert_eq!(mu, expected_mu);
202+
}
203+
204+
#[test]
205+
fn test_compute_mu_parameter_2() {
206+
let modulus = U384 {
207+
limbs: [
208+
0,
209+
0,
210+
0,
211+
3450888597,
212+
5754816256417943771,
213+
15923941673896418529,
214+
],
215+
};
216+
let mu = compute_mu_parameter(&modulus);
217+
let expected_mu: u64 = 16085280245840369887;
218+
assert_eq!(mu, expected_mu);
219+
}
220+
221+
#[test]
222+
fn test_compute_mu_parameter_3() {
223+
let modulus = U384 {
224+
limbs: [
225+
18446744073709551615,
226+
18446744073709551615,
227+
18446744073709551615,
228+
18446744073709551615,
229+
18446744073709551615,
230+
18446744073709551275,
231+
],
232+
};
233+
let mu = compute_mu_parameter(&modulus);
234+
let expected_mu: u64 = 14984598558409225213;
235+
assert_eq!(mu, expected_mu);
236+
}
237+
238+
#[test]
239+
fn test_compute_r2_parameter_1() {
240+
let modulus = U384 {
241+
limbs: [0, 0, 0, 0, 0, 23],
242+
};
243+
let r2 = compute_r2_parameter(&modulus);
244+
let expected_r2 = U384::from_u64(6);
245+
assert_eq!(r2, expected_r2);
246+
}
247+
248+
#[test]
249+
fn test_compute_r2_parameter_2() {
250+
let modulus = U384 {
251+
limbs: [
252+
0,
253+
0,
254+
0,
255+
3450888597,
256+
5754816256417943771,
257+
15923941673896418529,
258+
],
259+
};
260+
let r2 = compute_r2_parameter(&modulus);
261+
let expected_r2 = U384 {
262+
limbs: [0, 0, 0, 362264696, 173086217205162856, 7848132598488868435],
263+
};
264+
assert_eq!(r2, expected_r2);
265+
}
266+
267+
#[test]
268+
fn test_compute_r2_parameter_3() {
269+
let modulus = U384 {
270+
limbs: [
271+
18446744073709551615,
272+
18446744073709551615,
273+
18446744073709551615,
274+
18446744073709551615,
275+
18446744073709551615,
276+
18446744073709551275,
277+
],
278+
};
279+
let r2 = compute_r2_parameter(&modulus);
280+
let expected_r2 = U384 {
281+
limbs: [0, 0, 0, 0, 0, 116281],
282+
};
283+
assert_eq!(r2, expected_r2);
284+
}
285+
139286
// F23
140287
#[derive(Clone, Debug)]
141288
struct MontgomeryConfig23;
142289
impl IsMontgomeryConfiguration for MontgomeryConfig23 {
143290
const MODULUS: U384 = UnsignedInteger::from_u64(23);
144-
const MP: u64 = 3208129404123400281;
145-
const R2: U384 = UnsignedInteger::from_u64(6);
146291
}
147292

148293
type F23 = MontgomeryBackendPrimeField<MontgomeryConfig23>;
@@ -305,10 +450,6 @@ mod tests {
305450
15923941673896418529,
306451
],
307452
};
308-
const MP: u64 = 16085280245840369887;
309-
const R2: U384 = UnsignedInteger {
310-
limbs: [0, 0, 0, 362264696, 173086217205162856, 7848132598488868435],
311-
};
312453
}
313454

314455
#[test]
@@ -355,10 +496,6 @@ mod tests {
355496
18446744073709551275,
356497
],
357498
};
358-
const MP: u64 = 14984598558409225213;
359-
const R2: U384 = UnsignedInteger {
360-
limbs: [0, 0, 0, 0, 0, 116281],
361-
};
362499
}
363500

364501
type FP2 = MontgomeryBackendPrimeField<MontgomeryConfigP2>;

0 commit comments

Comments
 (0)