@@ -5,16 +5,68 @@ use crate::{
5
5
field:: traits:: IsField , unsigned_integer:: element:: UnsignedInteger ,
6
6
unsigned_integer:: montgomery:: MontgomeryAlgorithms ,
7
7
} ;
8
+
8
9
use std:: fmt:: Debug ;
9
10
use std:: marker:: PhantomData ;
10
11
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
+
11
63
/// This trait is necessary for us to be able to use unsigned integer types bigger than
12
64
/// `u128` (the biggest native `unit`) as constant generics.
13
65
/// This trait should be removed when Rust supports this feature.
14
66
pub trait IsMontgomeryConfiguration {
15
67
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 ) ;
18
70
}
19
71
20
72
#[ derive( Clone , Debug ) ]
50
102
}
51
103
52
104
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 )
54
106
}
55
107
56
108
fn sub ( a : & Self :: BaseType , b : & Self :: BaseType ) -> Self :: BaseType {
@@ -93,11 +145,11 @@ where
93
145
}
94
146
95
147
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 )
97
149
}
98
150
99
151
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 )
101
153
}
102
154
}
103
155
@@ -106,12 +158,12 @@ where
106
158
C : IsMontgomeryConfiguration + Clone + Debug ,
107
159
{
108
160
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 )
110
162
. to_bytes_be ( )
111
163
}
112
164
113
165
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 )
115
167
. to_bytes_le ( )
116
168
}
117
169
@@ -129,20 +181,113 @@ where
129
181
#[ cfg( test) ]
130
182
mod tests {
131
183
use crate :: {
132
- field:: element:: FieldElement ,
184
+ field:: {
185
+ element:: FieldElement ,
186
+ fields:: u384_prime_field:: { compute_mu_parameter, compute_r2_parameter} ,
187
+ } ,
133
188
traits:: ByteConversion ,
134
189
unsigned_integer:: element:: { UnsignedInteger , U384 } ,
135
190
} ;
136
191
137
192
use super :: { IsMontgomeryConfiguration , MontgomeryBackendPrimeField } ;
138
193
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
+
139
286
// F23
140
287
#[ derive( Clone , Debug ) ]
141
288
struct MontgomeryConfig23 ;
142
289
impl IsMontgomeryConfiguration for MontgomeryConfig23 {
143
290
const MODULUS : U384 = UnsignedInteger :: from_u64 ( 23 ) ;
144
- const MP : u64 = 3208129404123400281 ;
145
- const R2 : U384 = UnsignedInteger :: from_u64 ( 6 ) ;
146
291
}
147
292
148
293
type F23 = MontgomeryBackendPrimeField < MontgomeryConfig23 > ;
@@ -305,10 +450,6 @@ mod tests {
305
450
15923941673896418529 ,
306
451
] ,
307
452
} ;
308
- const MP : u64 = 16085280245840369887 ;
309
- const R2 : U384 = UnsignedInteger {
310
- limbs : [ 0 , 0 , 0 , 362264696 , 173086217205162856 , 7848132598488868435 ] ,
311
- } ;
312
453
}
313
454
314
455
#[ test]
@@ -355,10 +496,6 @@ mod tests {
355
496
18446744073709551275 ,
356
497
] ,
357
498
} ;
358
- const MP : u64 = 14984598558409225213 ;
359
- const R2 : U384 = UnsignedInteger {
360
- limbs : [ 0 , 0 , 0 , 0 , 0 , 116281 ] ,
361
- } ;
362
499
}
363
500
364
501
type FP2 = MontgomeryBackendPrimeField < MontgomeryConfigP2 > ;
0 commit comments