Skip to content

Commit 745ff62

Browse files
committed
Use optimized map_to_curve_elligator2_curve448()
1 parent 6243a35 commit 745ff62

File tree

2 files changed

+184
-53
lines changed

2 files changed

+184
-53
lines changed

ed448-goldilocks/src/edwards/affine.rs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -86,36 +86,36 @@ impl AffinePoint {
8686
}
8787
}
8888

89-
pub(crate) fn isogeny(&self) -> Self {
90-
let x = self.x;
91-
let y = self.y;
92-
let mut t0 = x.square(); // x^2
93-
let t1 = t0 + FieldElement::ONE; // x^2+1
94-
t0 -= FieldElement::ONE; // x^2-1
95-
let mut t2 = y.square(); // y^2
96-
t2 = t2.double(); // 2y^2
97-
let t3 = x.double(); // 2x
98-
99-
let mut t4 = t0 * y; // y(x^2-1)
100-
t4 = t4.double(); // 2y(x^2-1)
101-
let xNum = t4.double(); // xNum = 4y(x^2-1)
102-
103-
let mut t5 = t0.square(); // x^4-2x^2+1
104-
t4 = t5 + t2; // x^4-2x^2+1+2y^2
105-
let xDen = t4 + t2; // xDen = x^4-2x^2+1+4y^2
106-
107-
t5 *= x; // x^5-2x^3+x
108-
t4 = t2 * t3; // 4xy^2
109-
let yNum = t4 - t5; // yNum = -(x^5-2x^3+x-4xy^2)
110-
111-
t4 = t1 * t2; // 2x^2y^2+2y^2
112-
let yDen = t5 - t4; // yDen = x^5-2x^3+x-2x^2y^2-2y^2
113-
114-
Self {
115-
x: xNum * xDen.invert(),
116-
y: yNum * yDen.invert(),
117-
}
118-
}
89+
// pub(crate) fn isogeny(&self) -> Self {
90+
// let x = self.x;
91+
// let y = self.y;
92+
// let mut t0 = x.square(); // x^2
93+
// let t1 = t0 + FieldElement::ONE; // x^2+1
94+
// t0 -= FieldElement::ONE; // x^2-1
95+
// let mut t2 = y.square(); // y^2
96+
// t2 = t2.double(); // 2y^2
97+
// let t3 = x.double(); // 2x
98+
99+
// let mut t4 = t0 * y; // y(x^2-1)
100+
// t4 = t4.double(); // 2y(x^2-1)
101+
// let xNum = t4.double(); // xNum = 4y(x^2-1)
102+
103+
// let mut t5 = t0.square(); // x^4-2x^2+1
104+
// t4 = t5 + t2; // x^4-2x^2+1+2y^2
105+
// let xDen = t4 + t2; // xDen = x^4-2x^2+1+4y^2
106+
107+
// t5 *= x; // x^5-2x^3+x
108+
// t4 = t2 * t3; // 4xy^2
109+
// let yNum = t4 - t5; // yNum = -(x^5-2x^3+x-4xy^2)
110+
111+
// t4 = t1 * t2; // 2x^2y^2+2y^2
112+
// let yDen = t5 - t4; // yDen = x^5-2x^3+x-2x^2y^2-2y^2
113+
114+
// Self {
115+
// x: xNum * xDen.invert(),
116+
// y: yNum * yDen.invert(),
117+
// }
118+
// }
119119

120120
/// Standard compression; store Y and sign of X
121121
pub fn compress(&self) -> CompressedEdwardsY {

ed448-goldilocks/src/field/element.rs

Lines changed: 154 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
44

55
use super::{ConstMontyType, MODULUS};
66
use crate::{
7-
AffinePoint, Decaf448, DecafPoint, Ed448, EdwardsPoint,
7+
Decaf448, DecafPoint, Ed448, EdwardsPoint,
88
curve::twedwards::extended::ExtendedPoint as TwistedExtendedPoint,
99
};
1010
use elliptic_curve::ops::Reduce;
@@ -196,7 +196,7 @@ impl MapToCurve for Ed448 {
196196
type ScalarLength = U84;
197197

198198
fn map_to_curve(element: FieldElement) -> EdwardsPoint {
199-
element.map_to_curve_elligator2().isogeny().to_edwards()
199+
element.map_to_curve_elligator2_edwards448()
200200
}
201201
}
202202

@@ -304,6 +304,11 @@ impl FieldElement {
304304
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
305305
)));
306306
pub const ZERO: Self = Self(ConstMontyType::new(&U448::ZERO));
307+
// See https://www.rfc-editor.org/rfc/rfc9380.html#name-curve448-q-3-mod-4-k-1.
308+
// 1. c1 = (q - 3) / 4 # Integer arithmetic
309+
const C1: U448 = U448::from_be_hex(
310+
"3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffffffffffffffffffffffffffffffffffffffffffffffffff",
311+
);
307312

308313
pub fn is_negative(&self) -> Choice {
309314
self.0.retrieve().is_odd()
@@ -426,27 +431,153 @@ impl FieldElement {
426431
Self(self.0.div_by_2())
427432
}
428433

429-
pub(crate) fn map_to_curve_elligator2(&self) -> AffinePoint {
430-
let mut t1 = self.square(); // 1. t1 = u^2
431-
t1 *= Self::Z; // 2. t1 = Z * t1 // Z * u^2
432-
let e1 = t1.ct_eq(&Self::MINUS_ONE); // 3. e1 = t1 == -1 // exceptional case: Z * u^2 == -1
433-
t1.conditional_assign(&Self::ZERO, e1); // 4. t1 = CMOV(t1, 0, e1) // if t1 == -1, set t1 = 0
434-
let mut x1 = t1 + Self::ONE; // 5. x1 = t1 + 1
435-
x1 = x1.invert(); // 6. x1 = inv0(x1)
436-
x1 *= -Self::J; // 7. x1 = -A * x1 // x1 = -A / (1 + Z * u^2)
437-
let mut gx1 = x1 + Self::J; // 8. gx1 = x1 + A
438-
gx1 *= x1; // 9. gx1 = gx1 * x1
439-
gx1 += Self::ONE; // 10. gx1 = gx1 + B
440-
gx1 *= x1; // 11. gx1 = gx1 * x1 // gx1 = x1^3 + A * x1^2 + B * x1
441-
let x2 = -x1 - Self::J; // 12. x2 = -x1 - A
442-
let gx2 = t1 * gx1; // 13. gx2 = t1 * gx1
443-
let e2 = gx1.is_square(); // 14. e2 = is_square(gx1)
444-
let x = Self::conditional_select(&x2, &x1, e2); // 15. x = CMOV(x2, x1, e2) // If is_square(gx1), x = x1, else x = x2
445-
let y2 = Self::conditional_select(&gx2, &gx1, e2); // 16. y2 = CMOV(gx2, gx1, e2) // If is_square(gx1), y2 = gx1, else y2 = gx2
446-
let mut y = y2.sqrt(); // 17. y = sqrt(y2)
447-
let e3 = y.is_negative(); // 18. e3 = sgn0(y) == 1
448-
y.conditional_negate(e2 ^ e3); // y = CMOV(-y, y, e2 xor e3)
449-
AffinePoint { x, y }
434+
// See https://www.rfc-editor.org/rfc/rfc9380.html#name-curve448-q-3-mod-4-k-1.
435+
pub(crate) fn map_to_curve_elligator2_curve448(
436+
&self,
437+
) -> (FieldElement, FieldElement, FieldElement) {
438+
// 1. tv1 = u^2
439+
let mut tv1 = self.square();
440+
// 2. e1 = tv1 == 1
441+
let e1 = tv1.ct_eq(&FieldElement::ONE);
442+
// 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0
443+
tv1.conditional_assign(&FieldElement::ZERO, e1);
444+
// 4. xd = 1 - tv1
445+
let xd = FieldElement::ONE - tv1;
446+
// 5. x1n = -J
447+
let x1n = -Self::J;
448+
// 6. tv2 = xd^2
449+
let tv2 = xd.square();
450+
// 7. gxd = tv2 * xd # gxd = xd^3
451+
let gxd = tv2 * xd;
452+
// 8. gx1 = -J * tv1 # x1n + J * xd
453+
let mut gx1 = x1n * tv1;
454+
// 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
455+
gx1 *= x1n;
456+
// 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
457+
gx1 += tv2;
458+
// 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
459+
gx1 *= x1n;
460+
// 12. tv3 = gxd^2
461+
let tv3 = gxd.square();
462+
// 13. tv2 = gx1 * gxd # gx1 * gxd
463+
let tv2 = gx1 * gxd;
464+
// 14. tv3 = tv3 * tv2 # gx1 * gxd^3
465+
let tv3 = tv3 * tv2;
466+
// 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4)
467+
let mut y1 = FieldElement(tv3.0.pow(&Self::C1));
468+
// 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4)
469+
y1 *= tv2;
470+
// 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd
471+
let x2n = -tv1 * x1n;
472+
// 18. y2 = y1 * u
473+
let mut y2 = y1 * self;
474+
// 19. y2 = CMOV(y2, 0, e1)
475+
y2.conditional_assign(&FieldElement::ZERO, e1);
476+
// 20. tv2 = y1^2
477+
let mut tv2 = y1.square();
478+
// 21. tv2 = tv2 * gxd
479+
tv2 *= gxd;
480+
// 22. e2 = tv2 == gx1
481+
let e2 = tv2.ct_eq(&gx1);
482+
// 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2
483+
let xn = FieldElement::conditional_select(&x2n, &x1n, e2);
484+
// 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2
485+
let mut y = FieldElement::conditional_select(&y2, &y1, e2);
486+
// 25. e3 = sgn0(y) == 1 # Fix sign of y
487+
let e3 = y.is_negative();
488+
// 26. y = CMOV(y, -y, e2 XOR e3)
489+
y.conditional_negate(e2 ^ e3);
490+
// 27. return (xn, xd, y, 1)
491+
492+
(xn, xd, y)
493+
}
494+
495+
fn map_to_curve_elligator2_edwards448(&self) -> EdwardsPoint {
496+
// 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)
497+
let (xn, xd, yn) = self.map_to_curve_elligator2_curve448();
498+
// 2. xn2 = xn^2
499+
let xn2 = xn.square();
500+
// 3. xd2 = xd^2
501+
let xd2 = xd.square();
502+
// 4. xd4 = xd2^2
503+
let xd4 = xd2.square();
504+
// 5. yn2 = yn^2
505+
let yn2 = yn.square();
506+
// 6. yd2 = yd^2
507+
let yd2 = FieldElement::ONE;
508+
// 7. xEn = xn2 - xd2
509+
let mut xEn = xn2 - xd2;
510+
// 8. tv2 = xEn - xd2
511+
let mut tv2 = xEn - xd2;
512+
// 9. xEn = xEn * xd2
513+
xEn *= xd2;
514+
// 10. xEn = xEn * yd
515+
// SKIP: yd = 1
516+
// 11. xEn = xEn * yn
517+
xEn *= yn;
518+
// 12. xEn = xEn * 4
519+
xEn = xEn.double().double();
520+
// 13. tv2 = tv2 * xn2
521+
tv2 *= xn2;
522+
// 14. tv2 = tv2 * yd2
523+
// SKIP: yd2 = 1
524+
// 15. tv3 = 4 * yn2
525+
let tv3 = yn2.double().double();
526+
// 16. tv1 = tv3 + yd2
527+
let mut tv1 = tv3 + yd2;
528+
// 17. tv1 = tv1 * xd4
529+
tv1 *= xd4;
530+
// 18. xEd = tv1 + tv2
531+
let mut xEd = tv1 + tv2;
532+
// 19. tv2 = tv2 * xn
533+
tv2 *= xn;
534+
// 20. tv4 = xn * xd4
535+
let tv4 = xn * xd4;
536+
// 21. yEn = tv3 - yd2
537+
let mut yEn = tv3 - yd2;
538+
// 22. yEn = yEn * tv4
539+
yEn *= tv4;
540+
// 23. yEn = yEn - tv2
541+
yEn -= tv2;
542+
// 24. tv1 = xn2 + xd2
543+
let mut tv1 = xn2 + xd2;
544+
// 25. tv1 = tv1 * xd2
545+
tv1 *= xd2;
546+
// 26. tv1 = tv1 * xd
547+
tv1 *= xd;
548+
// 27. tv1 = tv1 * yn2
549+
tv1 *= yn2;
550+
// 28. tv1 = -2 * tv1
551+
tv1 *= -FieldElement::TWO;
552+
// 29. yEd = tv2 + tv1
553+
let mut yEd = tv2 + tv1;
554+
// 30. tv4 = tv4 * yd2
555+
// SKIP: yd2 = 1
556+
// 31. yEd = yEd + tv4
557+
yEd += tv4;
558+
// 32. tv1 = xEd * yEd
559+
let tv1 = xEd * yEd;
560+
// 33. e = tv1 == 0
561+
let e = tv1.ct_eq(&FieldElement::ZERO);
562+
// 34. xEn = CMOV(xEn, 0, e)
563+
xEn.conditional_assign(&FieldElement::ZERO, e);
564+
// 35. xEd = CMOV(xEd, 1, e)
565+
xEd.conditional_assign(&FieldElement::ONE, e);
566+
// 36. yEn = CMOV(yEn, 1, e)
567+
yEn.conditional_assign(&FieldElement::ONE, e);
568+
// 37. yEd = CMOV(yEd, 1, e)
569+
yEd.conditional_assign(&FieldElement::ONE, e);
570+
// 38. return (xEn, xEd, yEn, yEd)
571+
572+
// Output: (xn, xd, yn, yd) such that (xn / xd, yn / yd) is a
573+
// point on edwards448.
574+
575+
EdwardsPoint {
576+
X: xEn * yEd,
577+
Y: xEd * yEn,
578+
Z: xEd * yEd,
579+
T: xEn * yEn,
580+
}
450581
}
451582

452583
// See https://www.shiftleft.org/papers/decaf/decaf.pdf#section.A.3.

0 commit comments

Comments
 (0)