22
33#![ allow( clippy:: needless_range_loop, clippy:: op_ref) ]
44
5- use crate :: { AffinePoint , Field , PrimeCurveParams } ;
5+ use crate :: { AffinePoint , CurveEquationAIsMinusThree , Field , PrimeCurveParams } ;
66use core:: {
77 borrow:: Borrow ,
88 iter:: Sum ,
@@ -136,38 +136,6 @@ where
136136 ret
137137 }
138138
139- /// Doubles this point.
140- pub fn double ( & self ) -> Self {
141- // We implement the exception-free point doubling formula from
142- // Renes-Costello-Batina 2015 (Algorithm 6). The comments after each line
143- // indicate which algorithm steps are being performed.
144-
145- let xx = self . x . square ( ) ; // 1
146- let yy = self . y . square ( ) ; // 2
147- let zz = self . z . square ( ) ; // 3
148- let xy2 = ( self . x * & self . y ) . double ( ) ; // 4, 5
149- let xz2 = ( self . x * & self . z ) . double ( ) ; // 6, 7
150-
151- let bzz_part = ( C :: EQUATION_B * & zz) - & xz2; // 8, 9
152- let bzz3_part = bzz_part. double ( ) + & bzz_part; // 10, 11
153- let yy_m_bzz3 = yy - & bzz3_part; // 12
154- let yy_p_bzz3 = yy + & bzz3_part; // 13
155- let y_frag = yy_p_bzz3 * & yy_m_bzz3; // 14
156- let x_frag = yy_m_bzz3 * & xy2; // 15
157-
158- let zz3 = zz. double ( ) + & zz; // 16, 17
159- let bxz2_part = ( C :: EQUATION_B * & xz2) - & ( zz3 + & xx) ; // 18, 19, 20
160- let bxz6_part = bxz2_part. double ( ) + & bxz2_part; // 21, 22
161- let xx3_m_zz3 = xx. double ( ) + & xx - & zz3; // 23, 24, 25
162-
163- let y = y_frag + & ( xx3_m_zz3 * & bxz6_part) ; // 26, 27
164- let yz2 = ( self . y * & self . z ) . double ( ) ; // 28, 29
165- let x = x_frag - & ( bxz6_part * & yz2) ; // 30, 31
166- let z = ( yz2 * & yy) . double ( ) . double ( ) ; // 32, 33, 34
167-
168- Self { x, y, z }
169- }
170-
171139 /// Returns `self - other`.
172140 pub fn sub ( & self , other : & Self ) -> Self {
173141 self . add ( & other. neg ( ) )
@@ -179,7 +147,10 @@ where
179147 }
180148
181149 /// Returns `[k] self`.
182- fn mul ( & self , k : & Scalar < C > ) -> Self {
150+ fn mul ( & self , k : & Scalar < C > ) -> Self
151+ where
152+ Self : Double ,
153+ {
183154 let k = Into :: < C :: UInt > :: into ( * k) . to_le_byte_array ( ) ;
184155
185156 let mut pc = [ Self :: default ( ) ; 16 ] ;
@@ -188,7 +159,7 @@ where
188159
189160 for i in 2 ..16 {
190161 pc[ i] = if i % 2 == 0 {
191- pc[ i / 2 ] . double ( )
162+ Double :: double ( & pc[ i / 2 ] )
192163 } else {
193164 pc[ i - 1 ] . add ( self )
194165 } ;
@@ -215,16 +186,68 @@ where
215186 break ;
216187 }
217188
218- q = q . double ( ) . double ( ) . double ( ) . double ( ) ;
189+ q = Double :: double ( & Double :: double ( & Double :: double ( & Double :: double ( & q ) ) ) ) ;
219190 pos -= 4 ;
220191 }
221192
222193 q
223194 }
224195}
225196
197+ /// Double a point (i.e. add it to itself)
198+ // TODO(tarcieri): extract this into `elliptic_curve::ops`
199+ pub trait Double {
200+ /// Double this point.
201+ fn double ( & self ) -> Self ;
202+ }
203+
204+ impl < C > Double for ProjectivePoint < C >
205+ where
206+ C : PrimeCurveParams + CurveEquationAIsMinusThree ,
207+ {
208+ /// We implement the exception-free point doubling formula from
209+ /// Renes-Costello-Batina 2015 (Algorithm 6), for prime order short
210+ /// Weierstrass curves `y² = x³ + ax + b` where `a = -3`.
211+ ///
212+ /// The comments after each lines indicate which algorithm steps
213+ /// are being performed.
214+ fn double ( & self ) -> Self {
215+ debug_assert_eq ! (
216+ C :: EQUATION_A ,
217+ -C :: FieldElement :: from( 3 ) ,
218+ "this implementation is only valid for C::EQUATION_A = -3"
219+ ) ;
220+
221+ let xx = self . x . square ( ) ; // 1
222+ let yy = self . y . square ( ) ; // 2
223+ let zz = self . z . square ( ) ; // 3
224+ let xy2 = ( self . x * & self . y ) . double ( ) ; // 4, 5
225+ let xz2 = ( self . x * & self . z ) . double ( ) ; // 6, 7
226+
227+ let bzz_part = ( C :: EQUATION_B * & zz) - & xz2; // 8, 9
228+ let bzz3_part = bzz_part. double ( ) + & bzz_part; // 10, 11
229+ let yy_m_bzz3 = yy - & bzz3_part; // 12
230+ let yy_p_bzz3 = yy + & bzz3_part; // 13
231+ let y_frag = yy_p_bzz3 * & yy_m_bzz3; // 14
232+ let x_frag = yy_m_bzz3 * & xy2; // 15
233+
234+ let zz3 = zz. double ( ) + & zz; // 16, 17
235+ let bxz2_part = ( C :: EQUATION_B * & xz2) - & ( zz3 + & xx) ; // 18, 19, 20
236+ let bxz6_part = bxz2_part. double ( ) + & bxz2_part; // 21, 22
237+ let xx3_m_zz3 = xx. double ( ) + & xx - & zz3; // 23, 24, 25
238+
239+ let y = y_frag + & ( xx3_m_zz3 * & bxz6_part) ; // 26, 27
240+ let yz2 = ( self . y * & self . z ) . double ( ) ; // 28, 29
241+ let x = x_frag - & ( bxz6_part * & yz2) ; // 30, 31
242+ let z = ( yz2 * & yy) . double ( ) . double ( ) ; // 32, 33, 34
243+
244+ Self { x, y, z }
245+ }
246+ }
247+
226248impl < C > CofactorGroup for ProjectivePoint < C >
227249where
250+ Self : Double ,
228251 C : PrimeCurveParams ,
229252 FieldBytes < C > : Copy ,
230253 FieldSize < C > : ModulusSize ,
@@ -336,6 +359,7 @@ where
336359
337360impl < C > Group for ProjectivePoint < C >
338361where
362+ Self : Double ,
339363 C : PrimeCurveParams ,
340364{
341365 type Scalar = Scalar < C > ;
@@ -358,7 +382,7 @@ where
358382
359383 #[ must_use]
360384 fn double ( & self ) -> Self {
361- ProjectivePoint :: double ( self )
385+ Double :: double ( self )
362386 }
363387}
364388
@@ -388,6 +412,7 @@ where
388412
389413impl < C > group:: Curve for ProjectivePoint < C >
390414where
415+ Self : Double ,
391416 C : PrimeCurveParams ,
392417{
393418 type AffineRepr = AffinePoint < C > ;
@@ -397,10 +422,16 @@ where
397422 }
398423}
399424
400- impl < C > LinearCombination for ProjectivePoint < C > where C : PrimeCurveParams { }
425+ impl < C > LinearCombination for ProjectivePoint < C >
426+ where
427+ Self : Double ,
428+ C : PrimeCurveParams ,
429+ {
430+ }
401431
402432impl < C > PrimeGroup for ProjectivePoint < C >
403433where
434+ Self : Double ,
404435 C : PrimeCurveParams ,
405436 FieldBytes < C > : Copy ,
406437 FieldSize < C > : ModulusSize ,
@@ -411,6 +442,7 @@ where
411442
412443impl < C > PrimeCurve for ProjectivePoint < C >
413444where
445+ Self : Double ,
414446 C : PrimeCurveParams ,
415447 FieldBytes < C > : Copy ,
416448 FieldSize < C > : ModulusSize ,
@@ -691,6 +723,7 @@ where
691723
692724impl < C , S > Mul < S > for ProjectivePoint < C >
693725where
726+ Self : Double ,
694727 C : PrimeCurveParams ,
695728 S : Borrow < Scalar < C > > ,
696729{
@@ -704,6 +737,7 @@ where
704737impl < C > Mul < & Scalar < C > > for & ProjectivePoint < C >
705738where
706739 C : PrimeCurveParams ,
740+ ProjectivePoint < C > : Double ,
707741{
708742 type Output = ProjectivePoint < C > ;
709743
@@ -714,6 +748,7 @@ where
714748
715749impl < C , S > MulAssign < S > for ProjectivePoint < C >
716750where
751+ Self : Double ,
717752 C : PrimeCurveParams ,
718753 S : Borrow < Scalar < C > > ,
719754{
0 commit comments