@@ -12,7 +12,7 @@ use elliptic_curve::bigint::U448;
1212use elliptic_curve:: consts:: { U28 , U84 } ;
1313use hash2curve:: { ExpandMsg , ExpandMsgXof , Expander , FromOkm , MapToCurve } ;
1414use sha3:: Shake256 ;
15- use subtle:: { Choice , ConditionallyNegatable , ConditionallySelectable , ConstantTimeEq } ;
15+ use subtle:: { Choice , ConditionallyNegatable , ConditionallySelectable , ConstantTimeEq , CtOption } ;
1616
1717impl MontgomeryXpoint {
1818 /// First low order point on Curve448 and it's twist
@@ -112,19 +112,19 @@ impl MontgomeryXpoint {
112112 }
113113
114114 /// Compute the Y-coordinate
115- pub fn y ( & self , sign : Choice ) -> [ u8 ; 56 ] {
116- Self :: y_internal ( & FieldElement :: from_bytes ( & self . 0 ) , sign) . to_bytes ( )
115+ pub fn y ( & self , sign : Choice ) -> CtOption < [ u8 ; 56 ] > {
116+ Self :: y_internal ( & FieldElement :: from_bytes ( & self . 0 ) , sign) . map ( FieldElement :: to_bytes )
117117 }
118118
119119 // See https://www.rfc-editor.org/rfc/rfc7748#section-1.
120- pub ( super ) fn y_internal ( u : & FieldElement , sign : Choice ) -> FieldElement {
120+ pub ( super ) fn y_internal ( u : & FieldElement , sign : Choice ) -> CtOption < FieldElement > {
121121 // v^2 = u^3 + A*u^2 + u
122122 let uu = u. square ( ) ;
123123 let vv = uu * u + FieldElement :: J * uu + u;
124124
125125 let mut v = vv. sqrt ( ) ;
126126 v. conditional_negate ( v. is_negative ( ) ^ sign) ;
127- v
127+ CtOption :: new ( v , v . square ( ) . ct_eq ( & vv ) )
128128 }
129129
130130 pub ( super ) fn mul_internal (
@@ -160,21 +160,21 @@ impl MontgomeryXpoint {
160160 }
161161
162162 /// Convert the point to projective form including the y-coordinate
163- pub fn to_extended_projective ( & self , sign : Choice ) -> ProjectiveMontgomeryPoint {
163+ pub fn to_extended_projective ( & self , sign : Choice ) -> CtOption < ProjectiveMontgomeryPoint > {
164164 self . to_projective ( ) . to_extended ( sign)
165165 }
166166
167167 /// Convert the point to its form including the y-coordinate
168- pub fn to_extended ( & self , sign : Choice ) -> AffineMontgomeryPoint {
168+ pub fn to_extended ( & self , sign : Choice ) -> CtOption < AffineMontgomeryPoint > {
169169 let x = FieldElement :: from_bytes ( & self . 0 ) ;
170170 let y = Self :: y_internal ( & x, sign) ;
171171
172- AffineMontgomeryPoint :: new ( x, y)
172+ y . map ( |y| AffineMontgomeryPoint :: new ( x, y) )
173173 }
174174
175175 /// Convert this point to an [`AffinePoint`]
176- pub fn to_edwards ( & self , sign : Choice ) -> AffinePoint {
177- self . to_extended ( sign) . into ( )
176+ pub fn to_edwards ( & self , sign : Choice ) -> CtOption < AffinePoint > {
177+ self . to_extended ( sign) . map ( AffinePoint :: from )
178178 }
179179}
180180
@@ -273,14 +273,14 @@ impl ProjectiveMontgomeryXpoint {
273273 } ;
274274
275275 // See https://www.rfc-editor.org/rfc/rfc7748#section-1.
276- fn y ( & self , sign : Choice ) -> FieldElement {
276+ fn y ( & self , sign : Choice ) -> CtOption < FieldElement > {
277277 // v^2 = u^3 + A*u^2 + u
278278 let u_sq = self . U . square ( ) ;
279279 let v_sq = u_sq * self . U + FieldElement :: J * u_sq + self . U ;
280280
281281 let mut v = v_sq. sqrt ( ) ;
282282 v. conditional_negate ( v. is_negative ( ) ^ sign) ;
283- v
283+ CtOption :: new ( v , v . square ( ) . ct_eq ( & v_sq ) )
284284 }
285285
286286 /// Double this point
@@ -371,20 +371,30 @@ impl ProjectiveMontgomeryXpoint {
371371 }
372372
373373 /// Convert the point to affine form including the y-coordinate
374- pub fn to_extended_affine ( & self , sign : Choice ) -> AffineMontgomeryPoint {
374+ pub fn to_extended_affine ( & self , sign : Choice ) -> CtOption < AffineMontgomeryPoint > {
375375 let x = self . U * self . W . invert ( ) ;
376376 let y = self . y ( sign) ;
377377
378- AffineMontgomeryPoint :: new ( x, y)
378+ y . map ( |y| AffineMontgomeryPoint :: new ( x, y) )
379379 }
380380
381381 /// Convert the point to its form including the y-coordinate
382- pub fn to_extended ( & self , sign : Choice ) -> ProjectiveMontgomeryPoint {
383- ProjectiveMontgomeryPoint :: conditional_select (
384- & ProjectiveMontgomeryPoint :: new ( self . U , self . y ( sign) , self . W ) ,
385- & ProjectiveMontgomeryPoint :: IDENTITY ,
382+ pub fn to_extended ( & self , sign : Choice ) -> CtOption < ProjectiveMontgomeryPoint > {
383+ CtOption :: new (
384+ ProjectiveMontgomeryPoint :: IDENTITY ,
386385 self . ct_eq ( & Self :: IDENTITY ) ,
387386 )
387+ . or_else ( || {
388+ let y = self . y ( sign) ;
389+
390+ y. map ( |y| {
391+ ProjectiveMontgomeryPoint :: conditional_select (
392+ & ProjectiveMontgomeryPoint :: new ( self . U , y, self . W ) ,
393+ & ProjectiveMontgomeryPoint :: IDENTITY ,
394+ self . ct_eq ( & Self :: IDENTITY ) ,
395+ )
396+ } )
397+ } )
388398 }
389399}
390400
@@ -417,15 +427,15 @@ mod tests {
417427 let x_identity = ProjectiveMontgomeryXpoint :: IDENTITY ;
418428 let identity = ProjectiveMontgomeryPoint :: IDENTITY ;
419429
420- assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) , identity) ;
430+ assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) . unwrap ( ) , identity) ;
421431 }
422432
423433 #[ test]
424434 fn to_extended_affine ( ) {
425435 let x_identity = ProjectiveMontgomeryXpoint :: IDENTITY . to_affine ( ) ;
426436 let identity = ProjectiveMontgomeryPoint :: IDENTITY . to_affine ( ) ;
427437
428- assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) , identity) ;
438+ assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) . unwrap ( ) , identity) ;
429439 }
430440
431441 #[ test]
@@ -450,7 +460,7 @@ mod tests {
450460 yy. copy_from_slice ( & y[ ..] ) ;
451461 yy. reverse ( ) ;
452462 assert_eq ! ( p. 0 , xx) ;
453- assert ! ( p. y( Choice :: from( 0 ) ) == yy || p. y( Choice :: from( 1 ) ) == yy) ;
463+ assert ! ( p. y( Choice :: from( 0 ) ) . unwrap ( ) == yy || p. y( Choice :: from( 1 ) ) . unwrap ( ) == yy) ;
454464 }
455465 }
456466
@@ -476,7 +486,7 @@ mod tests {
476486 yy. copy_from_slice ( & y[ ..] ) ;
477487 yy. reverse ( ) ;
478488 assert_eq ! ( p. 0 , xx) ;
479- assert ! ( p. y( Choice :: from( 0 ) ) == yy || p. y( Choice :: from( 1 ) ) == yy) ;
489+ assert ! ( p. y( Choice :: from( 0 ) ) . unwrap ( ) == yy || p. y( Choice :: from( 1 ) ) . unwrap ( ) == yy) ;
480490 }
481491 }
482492}
0 commit comments