Skip to content

Commit dcf6aea

Browse files
committed
Use optimized map_to_curve_elligator2_curve448()
1 parent 579190a commit dcf6aea

File tree

2 files changed

+185
-53
lines changed

2 files changed

+185
-53
lines changed

ed448-goldilocks/src/edwards/affine.rs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -69,36 +69,36 @@ impl AffinePoint {
6969
y: FieldElement::ONE,
7070
};
7171

72-
pub(crate) fn isogeny(&self) -> Self {
73-
let x = self.x;
74-
let y = self.y;
75-
let mut t0 = x.square(); // x^2
76-
let t1 = t0 + FieldElement::ONE; // x^2+1
77-
t0 -= FieldElement::ONE; // x^2-1
78-
let mut t2 = y.square(); // y^2
79-
t2 = t2.double(); // 2y^2
80-
let t3 = x.double(); // 2x
81-
82-
let mut t4 = t0 * y; // y(x^2-1)
83-
t4 = t4.double(); // 2y(x^2-1)
84-
let xNum = t4.double(); // xNum = 4y(x^2-1)
85-
86-
let mut t5 = t0.square(); // x^4-2x^2+1
87-
t4 = t5 + t2; // x^4-2x^2+1+2y^2
88-
let xDen = t4 + t2; // xDen = x^4-2x^2+1+4y^2
89-
90-
t5 *= x; // x^5-2x^3+x
91-
t4 = t2 * t3; // 4xy^2
92-
let yNum = t4 - t5; // yNum = -(x^5-2x^3+x-4xy^2)
93-
94-
t4 = t1 * t2; // 2x^2y^2+2y^2
95-
let yDen = t5 - t4; // yDen = x^5-2x^3+x-2x^2y^2-2y^2
96-
97-
Self {
98-
x: xNum * xDen.invert(),
99-
y: yNum * yDen.invert(),
100-
}
101-
}
72+
// pub(crate) fn isogeny(&self) -> Self {
73+
// let x = self.x;
74+
// let y = self.y;
75+
// let mut t0 = x.square(); // x^2
76+
// let t1 = t0 + FieldElement::ONE; // x^2+1
77+
// t0 -= FieldElement::ONE; // x^2-1
78+
// let mut t2 = y.square(); // y^2
79+
// t2 = t2.double(); // 2y^2
80+
// let t3 = x.double(); // 2x
81+
82+
// let mut t4 = t0 * y; // y(x^2-1)
83+
// t4 = t4.double(); // 2y(x^2-1)
84+
// let xNum = t4.double(); // xNum = 4y(x^2-1)
85+
86+
// let mut t5 = t0.square(); // x^4-2x^2+1
87+
// t4 = t5 + t2; // x^4-2x^2+1+2y^2
88+
// let xDen = t4 + t2; // xDen = x^4-2x^2+1+4y^2
89+
90+
// t5 *= x; // x^5-2x^3+x
91+
// t4 = t2 * t3; // 4xy^2
92+
// let yNum = t4 - t5; // yNum = -(x^5-2x^3+x-4xy^2)
93+
94+
// t4 = t1 * t2; // 2x^2y^2+2y^2
95+
// let yDen = t5 - t4; // yDen = x^5-2x^3+x-2x^2y^2-2y^2
96+
97+
// Self {
98+
// x: xNum * xDen.invert(),
99+
// y: yNum * yDen.invert(),
100+
// }
101+
// }
102102

103103
/// Convert to edwards extended point
104104
pub fn to_edwards(&self) -> EdwardsPoint {

ed448-goldilocks/src/field/element.rs

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

44
use super::ConstMontyType;
55
use crate::{
6-
AffinePoint, Decaf448, DecafPoint, Ed448, EdwardsPoint,
6+
Decaf448, DecafPoint, Ed448, EdwardsPoint,
77
curve::twedwards::extended::ExtendedPoint as TwistedExtendedPoint,
88
};
99
use elliptic_curve::{
@@ -197,7 +197,7 @@ impl MapToCurve for Ed448 {
197197
type FieldElement = Ed448FieldElement;
198198

199199
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()
201201
}
202202

203203
fn map_to_subgroup(point: EdwardsPoint) -> EdwardsPoint {
@@ -246,6 +246,7 @@ impl FieldElement {
246246
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000262a8",
247247
)));
248248
pub const ONE: Self = Self(ConstMontyType::new(&U448::ONE));
249+
pub const TWO: Self = Self(ConstMontyType::new(&U448::from_u64(2)));
249250
pub const TWISTED_D: Self = Self(ConstMontyType::new(&U448::from_be_hex(
250251
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffff6755",
251252
)));
@@ -256,6 +257,11 @@ impl FieldElement {
256257
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
257258
)));
258259
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+
);
259265

260266
pub fn is_negative(&self) -> Choice {
261267
let bytes = self.to_bytes();
@@ -372,27 +378,153 @@ impl FieldElement {
372378
(inv_sqrt_x * u, zero_u | is_res)
373379
}
374380

375-
pub(crate) fn map_to_curve_elligator2(&self) -> AffinePoint {
376-
let mut t1 = self.square(); // 1. t1 = u^2
377-
t1 *= Self::Z; // 2. t1 = Z * t1 // Z * u^2
378-
let e1 = t1.ct_eq(&Self::MINUS_ONE); // 3. e1 = t1 == -1 // exceptional case: Z * u^2 == -1
379-
t1.conditional_assign(&Self::ZERO, e1); // 4. t1 = CMOV(t1, 0, e1) // if t1 == -1, set t1 = 0
380-
let mut x1 = t1 + Self::ONE; // 5. x1 = t1 + 1
381-
x1 = x1.invert(); // 6. x1 = inv0(x1)
382-
x1 *= -Self::J; // 7. x1 = -A * x1 // x1 = -A / (1 + Z * u^2)
383-
let mut gx1 = x1 + Self::J; // 8. gx1 = x1 + A
384-
gx1 *= x1; // 9. gx1 = gx1 * x1
385-
gx1 += Self::ONE; // 10. gx1 = gx1 + B
386-
gx1 *= x1; // 11. gx1 = gx1 * x1 // gx1 = x1^3 + A * x1^2 + B * x1
387-
let x2 = -x1 - Self::J; // 12. x2 = -x1 - A
388-
let gx2 = t1 * gx1; // 13. gx2 = t1 * gx1
389-
let e2 = gx1.is_square(); // 14. e2 = is_square(gx1)
390-
let x = Self::conditional_select(&x2, &x1, e2); // 15. x = CMOV(x2, x1, e2) // If is_square(gx1), x = x1, else x = x2
391-
let y2 = Self::conditional_select(&gx2, &gx1, e2); // 16. y2 = CMOV(gx2, gx1, e2) // If is_square(gx1), y2 = gx1, else y2 = gx2
392-
let mut y = y2.sqrt(); // 17. y = sqrt(y2)
393-
let e3 = y.is_negative(); // 18. e3 = sgn0(y) == 1
394-
y.conditional_negate(e2 ^ e3); // y = CMOV(-y, y, e2 xor e3)
395-
AffinePoint { x, y }
381+
// See https://www.rfc-editor.org/rfc/rfc9380.html#name-curve448-q-3-mod-4-k-1.
382+
pub(crate) fn map_to_curve_elligator2_curve448(
383+
&self,
384+
) -> (FieldElement, FieldElement, FieldElement) {
385+
// 1. tv1 = u^2
386+
let mut tv1 = self.square();
387+
// 2. e1 = tv1 == 1
388+
let e1 = tv1.ct_eq(&FieldElement::ONE);
389+
// 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0
390+
tv1.conditional_assign(&FieldElement::ZERO, e1);
391+
// 4. xd = 1 - tv1
392+
let xd = FieldElement::ONE - tv1;
393+
// 5. x1n = -J
394+
let x1n = -Self::J;
395+
// 6. tv2 = xd^2
396+
let tv2 = xd.square();
397+
// 7. gxd = tv2 * xd # gxd = xd^3
398+
let gxd = tv2 * xd;
399+
// 8. gx1 = -J * tv1 # x1n + J * xd
400+
let mut gx1 = x1n * tv1;
401+
// 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
402+
gx1 *= x1n;
403+
// 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
404+
gx1 += tv2;
405+
// 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
406+
gx1 *= x1n;
407+
// 12. tv3 = gxd^2
408+
let tv3 = gxd.square();
409+
// 13. tv2 = gx1 * gxd # gx1 * gxd
410+
let tv2 = gx1 * gxd;
411+
// 14. tv3 = tv3 * tv2 # gx1 * gxd^3
412+
let tv3 = tv3 * tv2;
413+
// 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4)
414+
let mut y1 = FieldElement(tv3.0.pow(&Self::C1));
415+
// 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4)
416+
y1 *= tv2;
417+
// 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd
418+
let x2n = -tv1 * x1n;
419+
// 18. y2 = y1 * u
420+
let mut y2 = y1 * self;
421+
// 19. y2 = CMOV(y2, 0, e1)
422+
y2.conditional_assign(&FieldElement::ZERO, e1);
423+
// 20. tv2 = y1^2
424+
let mut tv2 = y1.square();
425+
// 21. tv2 = tv2 * gxd
426+
tv2 *= gxd;
427+
// 22. e2 = tv2 == gx1
428+
let e2 = tv2.ct_eq(&gx1);
429+
// 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2
430+
let xn = FieldElement::conditional_select(&x2n, &x1n, e2);
431+
// 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2
432+
let mut y = FieldElement::conditional_select(&y2, &y1, e2);
433+
// 25. e3 = sgn0(y) == 1 # Fix sign of y
434+
let e3 = y.is_negative();
435+
// 26. y = CMOV(y, -y, e2 XOR e3)
436+
y.conditional_negate(e2 ^ e3);
437+
// 27. return (xn, xd, y, 1)
438+
439+
(xn, xd, y)
440+
}
441+
442+
fn map_to_curve_elligator2_edwards448(&self) -> EdwardsPoint {
443+
// 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)
444+
let (xn, xd, yn) = self.map_to_curve_elligator2_curve448();
445+
// 2. xn2 = xn^2
446+
let xn2 = xn.square();
447+
// 3. xd2 = xd^2
448+
let xd2 = xd.square();
449+
// 4. xd4 = xd2^2
450+
let xd4 = xd2.square();
451+
// 5. yn2 = yn^2
452+
let yn2 = yn.square();
453+
// 6. yd2 = yd^2
454+
let yd2 = FieldElement::ONE;
455+
// 7. xEn = xn2 - xd2
456+
let mut xEn = xn2 - xd2;
457+
// 8. tv2 = xEn - xd2
458+
let mut tv2 = xEn - xd2;
459+
// 9. xEn = xEn * xd2
460+
xEn *= xd2;
461+
// 10. xEn = xEn * yd
462+
// SKIP: yd = 1
463+
// 11. xEn = xEn * yn
464+
xEn *= yn;
465+
// 12. xEn = xEn * 4
466+
xEn = xEn.double().double();
467+
// 13. tv2 = tv2 * xn2
468+
tv2 *= xn2;
469+
// 14. tv2 = tv2 * yd2
470+
// SKIP: yd2 = 1
471+
// 15. tv3 = 4 * yn2
472+
let tv3 = yn2.double().double();
473+
// 16. tv1 = tv3 + yd2
474+
let mut tv1 = tv3 + yd2;
475+
// 17. tv1 = tv1 * xd4
476+
tv1 *= xd4;
477+
// 18. xEd = tv1 + tv2
478+
let mut xEd = tv1 + tv2;
479+
// 19. tv2 = tv2 * xn
480+
tv2 *= xn;
481+
// 20. tv4 = xn * xd4
482+
let tv4 = xn * xd4;
483+
// 21. yEn = tv3 - yd2
484+
let mut yEn = tv3 - yd2;
485+
// 22. yEn = yEn * tv4
486+
yEn *= tv4;
487+
// 23. yEn = yEn - tv2
488+
yEn -= tv2;
489+
// 24. tv1 = xn2 + xd2
490+
let mut tv1 = xn2 + xd2;
491+
// 25. tv1 = tv1 * xd2
492+
tv1 *= xd2;
493+
// 26. tv1 = tv1 * xd
494+
tv1 *= xd;
495+
// 27. tv1 = tv1 * yn2
496+
tv1 *= yn2;
497+
// 28. tv1 = -2 * tv1
498+
tv1 *= -FieldElement::TWO;
499+
// 29. yEd = tv2 + tv1
500+
let mut yEd = tv2 + tv1;
501+
// 30. tv4 = tv4 * yd2
502+
// SKIP: yd2 = 1
503+
// 31. yEd = yEd + tv4
504+
yEd += tv4;
505+
// 32. tv1 = xEd * yEd
506+
let tv1 = xEd * yEd;
507+
// 33. e = tv1 == 0
508+
let e = tv1.ct_eq(&FieldElement::ZERO);
509+
// 34. xEn = CMOV(xEn, 0, e)
510+
xEn.conditional_assign(&FieldElement::ZERO, e);
511+
// 35. xEd = CMOV(xEd, 1, e)
512+
xEd.conditional_assign(&FieldElement::ONE, e);
513+
// 36. yEn = CMOV(yEn, 1, e)
514+
yEn.conditional_assign(&FieldElement::ONE, e);
515+
// 37. yEd = CMOV(yEd, 1, e)
516+
yEd.conditional_assign(&FieldElement::ONE, e);
517+
// 38. return (xEn, xEd, yEn, yEd)
518+
519+
// Output: (xn, xd, yn, yd) such that (xn / xd, yn / yd) is a
520+
// point on edwards448.
521+
522+
EdwardsPoint {
523+
X: xEn * yEd,
524+
Y: xEd * yEn,
525+
Z: xEd * yEd,
526+
T: xEn * yEn,
527+
}
396528
}
397529

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

0 commit comments

Comments
 (0)