@@ -12,7 +12,7 @@ use elliptic_curve::bigint::U448;
12
12
use elliptic_curve:: consts:: { U28 , U84 } ;
13
13
use hash2curve:: { ExpandMsg , ExpandMsgXof , Expander , FromOkm , MapToCurve } ;
14
14
use sha3:: Shake256 ;
15
- use subtle:: { Choice , ConditionallyNegatable , ConditionallySelectable , ConstantTimeEq } ;
15
+ use subtle:: { Choice , ConditionallyNegatable , ConditionallySelectable , ConstantTimeEq , CtOption } ;
16
16
17
17
impl MontgomeryXpoint {
18
18
/// First low order point on Curve448 and it's twist
@@ -112,19 +112,19 @@ impl MontgomeryXpoint {
112
112
}
113
113
114
114
/// 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 )
117
117
}
118
118
119
119
// 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 > {
121
121
// v^2 = u^3 + A*u^2 + u
122
122
let uu = u. square ( ) ;
123
123
let vv = uu * u + FieldElement :: J * uu + u;
124
124
125
125
let mut v = vv. sqrt ( ) ;
126
126
v. conditional_negate ( v. is_negative ( ) ^ sign) ;
127
- v
127
+ CtOption :: new ( v , v . square ( ) . ct_eq ( & vv ) )
128
128
}
129
129
130
130
pub ( super ) fn mul_internal (
@@ -160,21 +160,21 @@ impl MontgomeryXpoint {
160
160
}
161
161
162
162
/// 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 > {
164
164
self . to_projective ( ) . to_extended ( sign)
165
165
}
166
166
167
167
/// 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 > {
169
169
let x = FieldElement :: from_bytes ( & self . 0 ) ;
170
170
let y = Self :: y_internal ( & x, sign) ;
171
171
172
- AffineMontgomeryPoint :: new ( x, y)
172
+ y . map ( |y| AffineMontgomeryPoint :: new ( x, y) )
173
173
}
174
174
175
175
/// 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 )
178
178
}
179
179
}
180
180
@@ -273,14 +273,14 @@ impl ProjectiveMontgomeryXpoint {
273
273
} ;
274
274
275
275
// 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 > {
277
277
// v^2 = u^3 + A*u^2 + u
278
278
let u_sq = self . U . square ( ) ;
279
279
let v_sq = u_sq * self . U + FieldElement :: J * u_sq + self . U ;
280
280
281
281
let mut v = v_sq. sqrt ( ) ;
282
282
v. conditional_negate ( v. is_negative ( ) ^ sign) ;
283
- v
283
+ CtOption :: new ( v , v . square ( ) . ct_eq ( & v_sq ) )
284
284
}
285
285
286
286
/// Double this point
@@ -365,20 +365,30 @@ impl ProjectiveMontgomeryXpoint {
365
365
}
366
366
367
367
/// Convert the point to affine form including the y-coordinate
368
- pub fn to_extended_affine ( & self , sign : Choice ) -> AffineMontgomeryPoint {
368
+ pub fn to_extended_affine ( & self , sign : Choice ) -> CtOption < AffineMontgomeryPoint > {
369
369
let x = self . U * self . W . invert ( ) ;
370
370
let y = self . y ( sign) ;
371
371
372
- AffineMontgomeryPoint :: new ( x, y)
372
+ y . map ( |y| AffineMontgomeryPoint :: new ( x, y) )
373
373
}
374
374
375
375
/// Convert the point to its form including the y-coordinate
376
- pub fn to_extended ( & self , sign : Choice ) -> ProjectiveMontgomeryPoint {
377
- ProjectiveMontgomeryPoint :: conditional_select (
378
- & ProjectiveMontgomeryPoint :: new ( self . U , self . y ( sign) , self . W ) ,
379
- & ProjectiveMontgomeryPoint :: IDENTITY ,
376
+ pub fn to_extended ( & self , sign : Choice ) -> CtOption < ProjectiveMontgomeryPoint > {
377
+ CtOption :: new (
378
+ ProjectiveMontgomeryPoint :: IDENTITY ,
380
379
self . ct_eq ( & Self :: IDENTITY ) ,
381
380
)
381
+ . or_else ( || {
382
+ let y = self . y ( sign) ;
383
+
384
+ y. map ( |y| {
385
+ ProjectiveMontgomeryPoint :: conditional_select (
386
+ & ProjectiveMontgomeryPoint :: new ( self . U , y, self . W ) ,
387
+ & ProjectiveMontgomeryPoint :: IDENTITY ,
388
+ self . ct_eq ( & Self :: IDENTITY ) ,
389
+ )
390
+ } )
391
+ } )
382
392
}
383
393
}
384
394
@@ -411,15 +421,15 @@ mod tests {
411
421
let x_identity = ProjectiveMontgomeryXpoint :: IDENTITY ;
412
422
let identity = ProjectiveMontgomeryPoint :: IDENTITY ;
413
423
414
- assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) , identity) ;
424
+ assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) . unwrap ( ) , identity) ;
415
425
}
416
426
417
427
#[ test]
418
428
fn to_extended_affine ( ) {
419
429
let x_identity = ProjectiveMontgomeryXpoint :: IDENTITY . to_affine ( ) ;
420
430
let identity = ProjectiveMontgomeryPoint :: IDENTITY . to_affine ( ) ;
421
431
422
- assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) , identity) ;
432
+ assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) . unwrap ( ) , identity) ;
423
433
}
424
434
425
435
#[ test]
@@ -443,7 +453,7 @@ mod tests {
443
453
yy. copy_from_slice ( & y[ ..] ) ;
444
454
yy. reverse ( ) ;
445
455
assert_eq ! ( p. 0 , xx) ;
446
- assert ! ( p. y( Choice :: from( 0 ) ) == yy || p. y( Choice :: from( 1 ) ) == yy) ;
456
+ assert ! ( p. y( Choice :: from( 0 ) ) . unwrap ( ) == yy || p. y( Choice :: from( 1 ) ) . unwrap ( ) == yy) ;
447
457
}
448
458
}
449
459
@@ -468,7 +478,7 @@ mod tests {
468
478
yy. copy_from_slice ( & y[ ..] ) ;
469
479
yy. reverse ( ) ;
470
480
assert_eq ! ( p. 0 , xx) ;
471
- assert ! ( p. y( Choice :: from( 0 ) ) == yy || p. y( Choice :: from( 1 ) ) == yy) ;
481
+ assert ! ( p. y( Choice :: from( 0 ) ) . unwrap ( ) == yy || p. y( Choice :: from( 1 ) ) . unwrap ( ) == yy) ;
472
482
}
473
483
}
474
484
}
0 commit comments