@@ -73,16 +73,16 @@ impl PartialEq for MontgomeryXpoint {
73
73
/// A Projective point in Montgomery form
74
74
#[ derive( Copy , Clone , Debug , Eq ) ]
75
75
pub struct ProjectiveMontgomeryXpoint {
76
- U : FieldElement ,
77
- W : FieldElement ,
76
+ pub ( super ) U : FieldElement ,
77
+ pub ( super ) W : FieldElement ,
78
78
}
79
79
80
80
impl Mul < & MontgomeryScalar > for & MontgomeryXpoint {
81
81
type Output = MontgomeryXpoint ;
82
82
83
83
#[ allow( clippy:: suspicious_arithmetic_impl) ]
84
84
fn mul ( self , scalar : & MontgomeryScalar ) -> MontgomeryXpoint {
85
- ( & self . to_projective ( ) * scalar) . to_affine ( )
85
+ self . mul_internal ( scalar) . 0 . to_affine ( )
86
86
}
87
87
}
88
88
@@ -118,6 +118,30 @@ impl MontgomeryXpoint {
118
118
self . to_projective ( ) . y ( sign) . to_bytes ( )
119
119
}
120
120
121
+ pub ( super ) fn mul_internal (
122
+ & self ,
123
+ scalar : & MontgomeryScalar ,
124
+ ) -> ( ProjectiveMontgomeryXpoint , ProjectiveMontgomeryXpoint ) {
125
+ // Algorithm 8 of Costello-Smith 2017
126
+ let mut x0 = ProjectiveMontgomeryXpoint :: IDENTITY ;
127
+ let mut x1 = self . to_projective ( ) ;
128
+ let diff = x1. U ;
129
+
130
+ let bits = scalar. bits ( ) ;
131
+ let mut swap = 0 ;
132
+ for s in ( 0 ..448 ) . rev ( ) {
133
+ let bit = bits[ s] as u8 ;
134
+ let choice: u8 = swap ^ bit;
135
+
136
+ ProjectiveMontgomeryXpoint :: conditional_swap ( & mut x0, & mut x1, Choice :: from ( choice) ) ;
137
+ differential_add_and_double ( & mut x0, & mut x1, & diff) ;
138
+
139
+ swap = bit;
140
+ }
141
+
142
+ ( x0, x1)
143
+ }
144
+
121
145
/// Convert the point to its form including the y-coordinate
122
146
pub fn to_projective ( & self ) -> ProjectiveMontgomeryXpoint {
123
147
ProjectiveMontgomeryXpoint {
@@ -166,25 +190,8 @@ impl PartialEq for ProjectiveMontgomeryXpoint {
166
190
impl Mul < & MontgomeryScalar > for & ProjectiveMontgomeryXpoint {
167
191
type Output = ProjectiveMontgomeryXpoint ;
168
192
169
- #[ allow( clippy:: suspicious_arithmetic_impl) ]
170
193
fn mul ( self , scalar : & MontgomeryScalar ) -> ProjectiveMontgomeryXpoint {
171
- // Algorithm 8 of Costello-Smith 2017
172
- let mut x0 = ProjectiveMontgomeryXpoint :: IDENTITY ;
173
- let mut x1 = * self ;
174
-
175
- let bits = scalar. bits ( ) ;
176
- let mut swap = 0 ;
177
- for s in ( 0 ..448 ) . rev ( ) {
178
- let bit = bits[ s] as u8 ;
179
- let choice: u8 = swap ^ bit;
180
-
181
- ProjectiveMontgomeryXpoint :: conditional_swap ( & mut x0, & mut x1, Choice :: from ( choice) ) ;
182
- differential_add_and_double ( & mut x0, & mut x1, & self . U ) ;
183
-
184
- swap = bit;
185
- }
186
-
187
- x0
194
+ self . to_affine ( ) . mul_internal ( scalar) . 0
188
195
}
189
196
}
190
197
@@ -196,6 +203,8 @@ impl Mul<&ProjectiveMontgomeryXpoint> for &MontgomeryScalar {
196
203
}
197
204
}
198
205
206
+ // (1987 Montgomery) Speeding the Pollard and elliptic curve methods of factorization
207
+ // fifth and sixth displays, plus common-subexpression elimination, plus assumption Z1=1
199
208
fn differential_add_and_double (
200
209
P : & mut ProjectiveMontgomeryXpoint ,
201
210
Q : & mut ProjectiveMontgomeryXpoint ,
@@ -371,11 +380,11 @@ mod tests {
371
380
let scalar = MontgomeryScalar :: from ( 200u32 ) ;
372
381
373
382
// Montgomery scalar mul
374
- let montgomery_res = ( & ProjectiveMontgomeryXpoint :: GENERATOR * & scalar) . to_affine ( ) ;
383
+ let montgomery_res =
384
+ ( & ( & ProjectiveMontgomeryXpoint :: GENERATOR * & scalar) * & scalar) . to_affine ( ) ;
375
385
// Goldilocks scalar mul
376
- let goldilocks_point = EdwardsPoint :: GENERATOR
377
- . scalar_mul ( & scalar. to_scalar ( ) )
378
- . to_affine ( ) ;
386
+ let goldilocks_point =
387
+ ( EdwardsPoint :: GENERATOR * scalar. to_scalar ( ) * scalar. to_scalar ( ) ) . to_affine ( ) ;
379
388
380
389
assert_eq ! ( goldilocks_point. to_montgomery_x( ) , montgomery_res) ;
381
390
}
0 commit comments