Skip to content

Commit a39b404

Browse files
authored
Add constant-time MontyParams::new (#518)
Adds a constant-time equivalent to `MontyParams::new_vartime`
1 parent efaaa05 commit a39b404

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

src/modular/monty_form.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use super::{
1313
reduction::montgomery_reduction,
1414
Retrieve,
1515
};
16-
use crate::{Limb, Monty, Odd, Uint, Word};
16+
use crate::{Concat, Limb, Monty, NonZero, Odd, Split, Uint, Word};
1717
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
1818

1919
/// Parameters to efficiently go to/from the Montgomery form for an odd modulus provided at runtime.
@@ -33,6 +33,42 @@ pub struct MontyParams<const LIMBS: usize> {
3333
}
3434

3535
impl<const LIMBS: usize> MontyParams<LIMBS> {
36+
/// Instantiates a new set of `MontyParams` representing the given odd `modulus`.
37+
pub fn new<const WIDE_LIMBS: usize>(modulus: Odd<Uint<LIMBS>>) -> Self
38+
where
39+
Uint<LIMBS>: Concat<Output = Uint<WIDE_LIMBS>>,
40+
Uint<WIDE_LIMBS>: Split<Output = Uint<LIMBS>>,
41+
{
42+
// `R mod modulus` where `R = 2^BITS`.
43+
// Represents 1 in Montgomery form.
44+
let one = Uint::MAX.rem(modulus.as_nz_ref()).wrapping_add(&Uint::ONE);
45+
46+
// `R^2 mod modulus`, used to convert integers to Montgomery form.
47+
let r2 = one
48+
.square()
49+
.rem(&NonZero(Uint::<LIMBS>::ZERO.concat(&modulus.0)))
50+
.split()
51+
.1;
52+
53+
// The modular inverse should always exist, because it was ensured odd above, which also ensures it's non-zero
54+
let inv_mod = modulus
55+
.inv_mod2k(Word::BITS)
56+
.expect("modular inverse should exist");
57+
58+
let mod_neg_inv = Limb(Word::MIN.wrapping_sub(inv_mod.limbs[0].0));
59+
60+
// `R^3 mod modulus`, used for inversion in Montgomery form.
61+
let r3 = montgomery_reduction(&r2.square_wide(), &modulus, mod_neg_inv);
62+
63+
Self {
64+
modulus,
65+
one,
66+
r2,
67+
r3,
68+
mod_neg_inv,
69+
}
70+
}
71+
3672
/// Instantiates a new set of `MontyParams` representing the given odd `modulus`.
3773
pub fn new_vartime(modulus: Odd<Uint<LIMBS>>) -> Self {
3874
// `R mod modulus` where `R = 2^BITS`.

tests/monty_form.proptest-regressions

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Seeds for failure cases proptest has generated in the past. It is
2+
# automatically read and these particular cases re-run before any
3+
# novel cases are generated.
4+
#
5+
# It is recommended to check this file in to source control so that
6+
# everyone who runs the test benefits from these saved cases.
7+
cc 19eef79040418fc32c4437caa30b98e5676e64e06ddf9afbd3eac59fb144577a # shrinks to n = MontyParams { modulus: Odd(Uint(0x0100000000000000000000000000000000000000000000000000000000000001)), one: Uint(0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01), r2: Uint(0x0000000000000000000000000000000000000000000000000000000000010000), r3: Uint(0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000001), mod_neg_inv: Limb(0xFFFFFFFFFFFFFFFF) }

tests/monty_form.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ prop_compose! {
3737
}
3838

3939
proptest! {
40+
#[test]
41+
fn new(n in modulus()) {
42+
let n2 = MontyParams::new(*n.modulus());
43+
prop_assert_eq!(n, n2);
44+
}
45+
4046
#[test]
4147
fn inv(x in uint(), n in modulus()) {
4248
let x = reduce(&x, n.clone());

0 commit comments

Comments
 (0)