@@ -3,7 +3,7 @@ use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
3
3
4
4
use super :: ConstMontyType ;
5
5
use crate :: {
6
- AffinePoint , Decaf448 , DecafPoint , Ed448 , EdwardsPoint ,
6
+ Decaf448 , DecafPoint , Ed448 , EdwardsPoint ,
7
7
curve:: twedwards:: extended:: ExtendedPoint as TwistedExtendedPoint ,
8
8
} ;
9
9
use elliptic_curve:: {
@@ -197,7 +197,7 @@ impl MapToCurve for Ed448 {
197
197
type FieldElement = Ed448FieldElement ;
198
198
199
199
fn map_to_curve ( element : Ed448FieldElement ) -> Self :: CurvePoint {
200
- element. 0 . map_to_curve_elligator2 ( ) . isogeny ( ) . to_edwards ( )
200
+ element. 0 . map_to_curve_elligator2_edwards448 ( )
201
201
}
202
202
203
203
fn map_to_subgroup ( point : EdwardsPoint ) -> EdwardsPoint {
@@ -257,6 +257,11 @@ impl FieldElement {
257
257
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffe" ,
258
258
) ) ) ;
259
259
pub const ZERO : Self = Self ( ConstMontyType :: new ( & U448 :: ZERO ) ) ;
260
+ // See https://www.rfc-editor.org/rfc/rfc9380.html#name-curve448-q-3-mod-4-k-1.
261
+ // 1. c1 = (q - 3) / 4 # Integer arithmetic
262
+ const C1 : U448 = U448 :: from_be_hex (
263
+ "3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffffffffffffffffffffffffffffffffffffffffff" ,
264
+ ) ;
260
265
261
266
pub fn is_negative ( & self ) -> Choice {
262
267
self . 0 . retrieve ( ) . is_odd ( )
@@ -369,27 +374,153 @@ impl FieldElement {
369
374
( inv_sqrt_x * u, zero_u | is_res)
370
375
}
371
376
372
- pub ( crate ) fn map_to_curve_elligator2 ( & self ) -> AffinePoint {
373
- let mut t1 = self . square ( ) ; // 1. t1 = u^2
374
- t1 *= Self :: Z ; // 2. t1 = Z * t1 // Z * u^2
375
- let e1 = t1. ct_eq ( & Self :: MINUS_ONE ) ; // 3. e1 = t1 == -1 // exceptional case: Z * u^2 == -1
376
- t1. conditional_assign ( & Self :: ZERO , e1) ; // 4. t1 = CMOV(t1, 0, e1) // if t1 == -1, set t1 = 0
377
- let mut x1 = t1 + Self :: ONE ; // 5. x1 = t1 + 1
378
- x1 = x1. invert ( ) ; // 6. x1 = inv0(x1)
379
- x1 *= -Self :: J ; // 7. x1 = -A * x1 // x1 = -A / (1 + Z * u^2)
380
- let mut gx1 = x1 + Self :: J ; // 8. gx1 = x1 + A
381
- gx1 *= x1; // 9. gx1 = gx1 * x1
382
- gx1 += Self :: ONE ; // 10. gx1 = gx1 + B
383
- gx1 *= x1; // 11. gx1 = gx1 * x1 // gx1 = x1^3 + A * x1^2 + B * x1
384
- let x2 = -x1 - Self :: J ; // 12. x2 = -x1 - A
385
- let gx2 = t1 * gx1; // 13. gx2 = t1 * gx1
386
- let e2 = gx1. is_square ( ) ; // 14. e2 = is_square(gx1)
387
- let x = Self :: conditional_select ( & x2, & x1, e2) ; // 15. x = CMOV(x2, x1, e2) // If is_square(gx1), x = x1, else x = x2
388
- let y2 = Self :: conditional_select ( & gx2, & gx1, e2) ; // 16. y2 = CMOV(gx2, gx1, e2) // If is_square(gx1), y2 = gx1, else y2 = gx2
389
- let mut y = y2. sqrt ( ) ; // 17. y = sqrt(y2)
390
- let e3 = y. is_negative ( ) ; // 18. e3 = sgn0(y) == 1
391
- y. conditional_negate ( e2 ^ e3) ; // y = CMOV(-y, y, e2 xor e3)
392
- AffinePoint { x, y }
377
+ // See https://www.rfc-editor.org/rfc/rfc9380.html#name-curve448-q-3-mod-4-k-1.
378
+ pub ( crate ) fn map_to_curve_elligator2_curve448 (
379
+ & self ,
380
+ ) -> ( FieldElement , FieldElement , FieldElement ) {
381
+ // 1. tv1 = u^2
382
+ let mut tv1 = self . square ( ) ;
383
+ // 2. e1 = tv1 == 1
384
+ let e1 = tv1. ct_eq ( & FieldElement :: ONE ) ;
385
+ // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0
386
+ tv1. conditional_assign ( & FieldElement :: ZERO , e1) ;
387
+ // 4. xd = 1 - tv1
388
+ let xd = FieldElement :: ONE - tv1;
389
+ // 5. x1n = -J
390
+ let x1n = -Self :: J ;
391
+ // 6. tv2 = xd^2
392
+ let tv2 = xd. square ( ) ;
393
+ // 7. gxd = tv2 * xd # gxd = xd^3
394
+ let gxd = tv2 * xd;
395
+ // 8. gx1 = -J * tv1 # x1n + J * xd
396
+ let mut gx1 = x1n * tv1;
397
+ // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
398
+ gx1 *= x1n;
399
+ // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
400
+ gx1 += tv2;
401
+ // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
402
+ gx1 *= x1n;
403
+ // 12. tv3 = gxd^2
404
+ let tv3 = gxd. square ( ) ;
405
+ // 13. tv2 = gx1 * gxd # gx1 * gxd
406
+ let tv2 = gx1 * gxd;
407
+ // 14. tv3 = tv3 * tv2 # gx1 * gxd^3
408
+ let tv3 = tv3 * tv2;
409
+ // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4)
410
+ let mut y1 = FieldElement ( tv3. 0 . pow ( & Self :: C1 ) ) ;
411
+ // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4)
412
+ y1 *= tv2;
413
+ // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd
414
+ let x2n = -tv1 * x1n;
415
+ // 18. y2 = y1 * u
416
+ let mut y2 = y1 * self ;
417
+ // 19. y2 = CMOV(y2, 0, e1)
418
+ y2. conditional_assign ( & FieldElement :: ZERO , e1) ;
419
+ // 20. tv2 = y1^2
420
+ let mut tv2 = y1. square ( ) ;
421
+ // 21. tv2 = tv2 * gxd
422
+ tv2 *= gxd;
423
+ // 22. e2 = tv2 == gx1
424
+ let e2 = tv2. ct_eq ( & gx1) ;
425
+ // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2
426
+ let xn = FieldElement :: conditional_select ( & x2n, & x1n, e2) ;
427
+ // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2
428
+ let mut y = FieldElement :: conditional_select ( & y2, & y1, e2) ;
429
+ // 25. e3 = sgn0(y) == 1 # Fix sign of y
430
+ let e3 = y. is_negative ( ) ;
431
+ // 26. y = CMOV(y, -y, e2 XOR e3)
432
+ y. conditional_negate ( e2 ^ e3) ;
433
+ // 27. return (xn, xd, y, 1)
434
+
435
+ ( xn, xd, y)
436
+ }
437
+
438
+ fn map_to_curve_elligator2_edwards448 ( & self ) -> EdwardsPoint {
439
+ // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)
440
+ let ( xn, xd, yn) = self . map_to_curve_elligator2_curve448 ( ) ;
441
+ // 2. xn2 = xn^2
442
+ let xn2 = xn. square ( ) ;
443
+ // 3. xd2 = xd^2
444
+ let xd2 = xd. square ( ) ;
445
+ // 4. xd4 = xd2^2
446
+ let xd4 = xd2. square ( ) ;
447
+ // 5. yn2 = yn^2
448
+ let yn2 = yn. square ( ) ;
449
+ // 6. yd2 = yd^2
450
+ let yd2 = FieldElement :: ONE ;
451
+ // 7. xEn = xn2 - xd2
452
+ let mut xEn = xn2 - xd2;
453
+ // 8. tv2 = xEn - xd2
454
+ let mut tv2 = xEn - xd2;
455
+ // 9. xEn = xEn * xd2
456
+ xEn *= xd2;
457
+ // 10. xEn = xEn * yd
458
+ // SKIP: yd = 1
459
+ // 11. xEn = xEn * yn
460
+ xEn *= yn;
461
+ // 12. xEn = xEn * 4
462
+ xEn = xEn. double ( ) . double ( ) ;
463
+ // 13. tv2 = tv2 * xn2
464
+ tv2 *= xn2;
465
+ // 14. tv2 = tv2 * yd2
466
+ // SKIP: yd2 = 1
467
+ // 15. tv3 = 4 * yn2
468
+ let tv3 = yn2. double ( ) . double ( ) ;
469
+ // 16. tv1 = tv3 + yd2
470
+ let mut tv1 = tv3 + yd2;
471
+ // 17. tv1 = tv1 * xd4
472
+ tv1 *= xd4;
473
+ // 18. xEd = tv1 + tv2
474
+ let mut xEd = tv1 + tv2;
475
+ // 19. tv2 = tv2 * xn
476
+ tv2 *= xn;
477
+ // 20. tv4 = xn * xd4
478
+ let tv4 = xn * xd4;
479
+ // 21. yEn = tv3 - yd2
480
+ let mut yEn = tv3 - yd2;
481
+ // 22. yEn = yEn * tv4
482
+ yEn *= tv4;
483
+ // 23. yEn = yEn - tv2
484
+ yEn -= tv2;
485
+ // 24. tv1 = xn2 + xd2
486
+ let mut tv1 = xn2 + xd2;
487
+ // 25. tv1 = tv1 * xd2
488
+ tv1 *= xd2;
489
+ // 26. tv1 = tv1 * xd
490
+ tv1 *= xd;
491
+ // 27. tv1 = tv1 * yn2
492
+ tv1 *= yn2;
493
+ // 28. tv1 = -2 * tv1
494
+ tv1 *= -FieldElement :: TWO ;
495
+ // 29. yEd = tv2 + tv1
496
+ let mut yEd = tv2 + tv1;
497
+ // 30. tv4 = tv4 * yd2
498
+ // SKIP: yd2 = 1
499
+ // 31. yEd = yEd + tv4
500
+ yEd += tv4;
501
+ // 32. tv1 = xEd * yEd
502
+ let tv1 = xEd * yEd;
503
+ // 33. e = tv1 == 0
504
+ let e = tv1. ct_eq ( & FieldElement :: ZERO ) ;
505
+ // 34. xEn = CMOV(xEn, 0, e)
506
+ xEn. conditional_assign ( & FieldElement :: ZERO , e) ;
507
+ // 35. xEd = CMOV(xEd, 1, e)
508
+ xEd. conditional_assign ( & FieldElement :: ONE , e) ;
509
+ // 36. yEn = CMOV(yEn, 1, e)
510
+ yEn. conditional_assign ( & FieldElement :: ONE , e) ;
511
+ // 37. yEd = CMOV(yEd, 1, e)
512
+ yEd. conditional_assign ( & FieldElement :: ONE , e) ;
513
+ // 38. return (xEn, xEd, yEn, yEd)
514
+
515
+ // Output: (xn, xd, yn, yd) such that (xn / xd, yn / yd) is a
516
+ // point on edwards448.
517
+
518
+ EdwardsPoint {
519
+ X : xEn * yEd,
520
+ Y : xEd * yEn,
521
+ Z : xEd * yEd,
522
+ T : xEn * yEn,
523
+ }
393
524
}
394
525
395
526
// See https://www.shiftleft.org/papers/decaf/decaf.pdf#section.A.3.
0 commit comments