@@ -4,7 +4,7 @@ use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
4
4
5
5
use super :: { ConstMontyType , MODULUS } ;
6
6
use crate :: {
7
- AffinePoint , Decaf448 , DecafPoint , Ed448 , EdwardsPoint ,
7
+ Decaf448 , DecafPoint , Ed448 , EdwardsPoint ,
8
8
curve:: twedwards:: extended:: ExtendedPoint as TwistedExtendedPoint ,
9
9
} ;
10
10
use elliptic_curve:: ops:: Reduce ;
@@ -198,7 +198,7 @@ impl MapToCurve for Ed448 {
198
198
type ScalarLength = U84 ;
199
199
200
200
fn map_to_curve ( element : FieldElement ) -> Self :: CurvePoint {
201
- element. map_to_curve_elligator2 ( ) . isogeny ( ) . to_edwards ( )
201
+ element. map_to_curve_elligator2_edwards448 ( )
202
202
}
203
203
204
204
fn map_to_subgroup ( point : EdwardsPoint ) -> EdwardsPoint {
@@ -319,6 +319,11 @@ impl FieldElement {
319
319
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffe" ,
320
320
) ) ) ;
321
321
pub const ZERO : Self = Self ( ConstMontyType :: new ( & U448 :: ZERO ) ) ;
322
+ // See https://www.rfc-editor.org/rfc/rfc9380.html#name-curve448-q-3-mod-4-k-1.
323
+ // 1. c1 = (q - 3) / 4 # Integer arithmetic
324
+ const C1 : U448 = U448 :: from_be_hex (
325
+ "3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffffffffffffffffffffffffffffffffffffffffff" ,
326
+ ) ;
322
327
323
328
pub fn is_negative ( & self ) -> Choice {
324
329
self . 0 . retrieve ( ) . is_odd ( )
@@ -441,27 +446,153 @@ impl FieldElement {
441
446
Self ( self . 0 . div_by_2 ( ) )
442
447
}
443
448
444
- pub ( crate ) fn map_to_curve_elligator2 ( & self ) -> AffinePoint {
445
- let mut t1 = self . square ( ) ; // 1. t1 = u^2
446
- t1 *= Self :: Z ; // 2. t1 = Z * t1 // Z * u^2
447
- let e1 = t1. ct_eq ( & Self :: MINUS_ONE ) ; // 3. e1 = t1 == -1 // exceptional case: Z * u^2 == -1
448
- t1. conditional_assign ( & Self :: ZERO , e1) ; // 4. t1 = CMOV(t1, 0, e1) // if t1 == -1, set t1 = 0
449
- let mut x1 = t1 + Self :: ONE ; // 5. x1 = t1 + 1
450
- x1 = x1. invert ( ) ; // 6. x1 = inv0(x1)
451
- x1 *= -Self :: J ; // 7. x1 = -A * x1 // x1 = -A / (1 + Z * u^2)
452
- let mut gx1 = x1 + Self :: J ; // 8. gx1 = x1 + A
453
- gx1 *= x1; // 9. gx1 = gx1 * x1
454
- gx1 += Self :: ONE ; // 10. gx1 = gx1 + B
455
- gx1 *= x1; // 11. gx1 = gx1 * x1 // gx1 = x1^3 + A * x1^2 + B * x1
456
- let x2 = -x1 - Self :: J ; // 12. x2 = -x1 - A
457
- let gx2 = t1 * gx1; // 13. gx2 = t1 * gx1
458
- let e2 = gx1. is_square ( ) ; // 14. e2 = is_square(gx1)
459
- let x = Self :: conditional_select ( & x2, & x1, e2) ; // 15. x = CMOV(x2, x1, e2) // If is_square(gx1), x = x1, else x = x2
460
- let y2 = Self :: conditional_select ( & gx2, & gx1, e2) ; // 16. y2 = CMOV(gx2, gx1, e2) // If is_square(gx1), y2 = gx1, else y2 = gx2
461
- let mut y = y2. sqrt ( ) ; // 17. y = sqrt(y2)
462
- let e3 = y. is_negative ( ) ; // 18. e3 = sgn0(y) == 1
463
- y. conditional_negate ( e2 ^ e3) ; // y = CMOV(-y, y, e2 xor e3)
464
- AffinePoint { x, y }
449
+ // See https://www.rfc-editor.org/rfc/rfc9380.html#name-curve448-q-3-mod-4-k-1.
450
+ pub ( crate ) fn map_to_curve_elligator2_curve448 (
451
+ & self ,
452
+ ) -> ( FieldElement , FieldElement , FieldElement ) {
453
+ // 1. tv1 = u^2
454
+ let mut tv1 = self . square ( ) ;
455
+ // 2. e1 = tv1 == 1
456
+ let e1 = tv1. ct_eq ( & FieldElement :: ONE ) ;
457
+ // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0
458
+ tv1. conditional_assign ( & FieldElement :: ZERO , e1) ;
459
+ // 4. xd = 1 - tv1
460
+ let xd = FieldElement :: ONE - tv1;
461
+ // 5. x1n = -J
462
+ let x1n = -Self :: J ;
463
+ // 6. tv2 = xd^2
464
+ let tv2 = xd. square ( ) ;
465
+ // 7. gxd = tv2 * xd # gxd = xd^3
466
+ let gxd = tv2 * xd;
467
+ // 8. gx1 = -J * tv1 # x1n + J * xd
468
+ let mut gx1 = x1n * tv1;
469
+ // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
470
+ gx1 *= x1n;
471
+ // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
472
+ gx1 += tv2;
473
+ // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
474
+ gx1 *= x1n;
475
+ // 12. tv3 = gxd^2
476
+ let tv3 = gxd. square ( ) ;
477
+ // 13. tv2 = gx1 * gxd # gx1 * gxd
478
+ let tv2 = gx1 * gxd;
479
+ // 14. tv3 = tv3 * tv2 # gx1 * gxd^3
480
+ let tv3 = tv3 * tv2;
481
+ // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4)
482
+ let mut y1 = FieldElement ( tv3. 0 . pow ( & Self :: C1 ) ) ;
483
+ // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4)
484
+ y1 *= tv2;
485
+ // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd
486
+ let x2n = -tv1 * x1n;
487
+ // 18. y2 = y1 * u
488
+ let mut y2 = y1 * self ;
489
+ // 19. y2 = CMOV(y2, 0, e1)
490
+ y2. conditional_assign ( & FieldElement :: ZERO , e1) ;
491
+ // 20. tv2 = y1^2
492
+ let mut tv2 = y1. square ( ) ;
493
+ // 21. tv2 = tv2 * gxd
494
+ tv2 *= gxd;
495
+ // 22. e2 = tv2 == gx1
496
+ let e2 = tv2. ct_eq ( & gx1) ;
497
+ // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2
498
+ let xn = FieldElement :: conditional_select ( & x2n, & x1n, e2) ;
499
+ // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2
500
+ let mut y = FieldElement :: conditional_select ( & y2, & y1, e2) ;
501
+ // 25. e3 = sgn0(y) == 1 # Fix sign of y
502
+ let e3 = y. is_negative ( ) ;
503
+ // 26. y = CMOV(y, -y, e2 XOR e3)
504
+ y. conditional_negate ( e2 ^ e3) ;
505
+ // 27. return (xn, xd, y, 1)
506
+
507
+ ( xn, xd, y)
508
+ }
509
+
510
+ fn map_to_curve_elligator2_edwards448 ( & self ) -> EdwardsPoint {
511
+ // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)
512
+ let ( xn, xd, yn) = self . map_to_curve_elligator2_curve448 ( ) ;
513
+ // 2. xn2 = xn^2
514
+ let xn2 = xn. square ( ) ;
515
+ // 3. xd2 = xd^2
516
+ let xd2 = xd. square ( ) ;
517
+ // 4. xd4 = xd2^2
518
+ let xd4 = xd2. square ( ) ;
519
+ // 5. yn2 = yn^2
520
+ let yn2 = yn. square ( ) ;
521
+ // 6. yd2 = yd^2
522
+ let yd2 = FieldElement :: ONE ;
523
+ // 7. xEn = xn2 - xd2
524
+ let mut xEn = xn2 - xd2;
525
+ // 8. tv2 = xEn - xd2
526
+ let mut tv2 = xEn - xd2;
527
+ // 9. xEn = xEn * xd2
528
+ xEn *= xd2;
529
+ // 10. xEn = xEn * yd
530
+ // SKIP: yd = 1
531
+ // 11. xEn = xEn * yn
532
+ xEn *= yn;
533
+ // 12. xEn = xEn * 4
534
+ xEn = xEn. double ( ) . double ( ) ;
535
+ // 13. tv2 = tv2 * xn2
536
+ tv2 *= xn2;
537
+ // 14. tv2 = tv2 * yd2
538
+ // SKIP: yd2 = 1
539
+ // 15. tv3 = 4 * yn2
540
+ let tv3 = yn2. double ( ) . double ( ) ;
541
+ // 16. tv1 = tv3 + yd2
542
+ let mut tv1 = tv3 + yd2;
543
+ // 17. tv1 = tv1 * xd4
544
+ tv1 *= xd4;
545
+ // 18. xEd = tv1 + tv2
546
+ let mut xEd = tv1 + tv2;
547
+ // 19. tv2 = tv2 * xn
548
+ tv2 *= xn;
549
+ // 20. tv4 = xn * xd4
550
+ let tv4 = xn * xd4;
551
+ // 21. yEn = tv3 - yd2
552
+ let mut yEn = tv3 - yd2;
553
+ // 22. yEn = yEn * tv4
554
+ yEn *= tv4;
555
+ // 23. yEn = yEn - tv2
556
+ yEn -= tv2;
557
+ // 24. tv1 = xn2 + xd2
558
+ let mut tv1 = xn2 + xd2;
559
+ // 25. tv1 = tv1 * xd2
560
+ tv1 *= xd2;
561
+ // 26. tv1 = tv1 * xd
562
+ tv1 *= xd;
563
+ // 27. tv1 = tv1 * yn2
564
+ tv1 *= yn2;
565
+ // 28. tv1 = -2 * tv1
566
+ tv1 *= -FieldElement :: TWO ;
567
+ // 29. yEd = tv2 + tv1
568
+ let mut yEd = tv2 + tv1;
569
+ // 30. tv4 = tv4 * yd2
570
+ // SKIP: yd2 = 1
571
+ // 31. yEd = yEd + tv4
572
+ yEd += tv4;
573
+ // 32. tv1 = xEd * yEd
574
+ let tv1 = xEd * yEd;
575
+ // 33. e = tv1 == 0
576
+ let e = tv1. ct_eq ( & FieldElement :: ZERO ) ;
577
+ // 34. xEn = CMOV(xEn, 0, e)
578
+ xEn. conditional_assign ( & FieldElement :: ZERO , e) ;
579
+ // 35. xEd = CMOV(xEd, 1, e)
580
+ xEd. conditional_assign ( & FieldElement :: ONE , e) ;
581
+ // 36. yEn = CMOV(yEn, 1, e)
582
+ yEn. conditional_assign ( & FieldElement :: ONE , e) ;
583
+ // 37. yEd = CMOV(yEd, 1, e)
584
+ yEd. conditional_assign ( & FieldElement :: ONE , e) ;
585
+ // 38. return (xEn, xEd, yEn, yEd)
586
+
587
+ // Output: (xn, xd, yn, yd) such that (xn / xd, yn / yd) is a
588
+ // point on edwards448.
589
+
590
+ EdwardsPoint {
591
+ X : xEn * yEd,
592
+ Y : xEd * yEn,
593
+ Z : xEd * yEd,
594
+ T : xEn * yEn,
595
+ }
465
596
}
466
597
467
598
// See https://www.shiftleft.org/papers/decaf/decaf.pdf#section.A.3.
0 commit comments