@@ -13,7 +13,7 @@ use super::{
13
13
reduction:: montgomery_reduction,
14
14
Retrieve ,
15
15
} ;
16
- use crate :: { Limb , Monty , Odd , Uint , Word } ;
16
+ use crate :: { Concat , Limb , Monty , NonZero , Odd , Split , Uint , Word } ;
17
17
use subtle:: { Choice , ConditionallySelectable , ConstantTimeEq } ;
18
18
19
19
/// 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> {
33
33
}
34
34
35
35
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
+
36
72
/// Instantiates a new set of `MontyParams` representing the given odd `modulus`.
37
73
pub fn new_vartime ( modulus : Odd < Uint < LIMBS > > ) -> Self {
38
74
// `R mod modulus` where `R = 2^BITS`.
0 commit comments