Skip to content

Commit b9a0167

Browse files
authored
ed448-goldilocks: optimize Edwards isogeny map further (#1350)
Fixes #1349
1 parent 30da3cc commit b9a0167

File tree

3 files changed

+73
-54
lines changed

3 files changed

+73
-54
lines changed

ed448-goldilocks/src/curve/twedwards.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,56 @@ pub(crate) mod affine;
66
pub(crate) mod extended;
77
pub(crate) mod extensible;
88
pub(crate) mod projective;
9+
10+
use crate::field::FieldElement;
11+
12+
pub(crate) struct IsogenyMap {
13+
pub(crate) X: FieldElement,
14+
pub(crate) Y: FieldElement,
15+
pub(crate) T: FieldElement,
16+
pub(crate) Z: FieldElement,
17+
}
18+
19+
impl IsogenyMap {
20+
// (1.) https://eprint.iacr.org/2014/027.pdf
21+
pub(crate) fn map(&self, scale: impl FnOnce(FieldElement) -> FieldElement) -> Self {
22+
// x = 2xy / (y^2 - a*x^2)
23+
// y = (y^2 + a*x^2) / (2 - y^2 - a*x^2)
24+
25+
// Derive algorithm for projective form:
26+
27+
// x = X / Z
28+
// y = Y / Z
29+
// xy = T / Z
30+
// x^2 = X^2 / Z^2
31+
// y^2 = y^2 / Z^2
32+
33+
// x = 2xy / (y^2 - a*x^2)
34+
// x = (2T/Z) / (Y^2/Z^2 + a*X^2/Z^2)
35+
// x = 2TZ / (Y^2 - a*X^2)
36+
37+
// y = (y^2 + a*x^2) / (2 - y^2 - a*x^2)
38+
// y = (Y^2/Z^2 + a*X^2/Z^2) / (2 - Y^2/Z^2 - a*X^2/Z^2)
39+
// y = (Y^2 + a*X^2) / (2*Z^2 - Y^2 - a*X^2)
40+
41+
let xx = self.X.square();
42+
let yy = self.Y.square();
43+
let axx = scale(xx);
44+
let yy_plus_axx = yy + axx;
45+
46+
// Compute x
47+
let x_numerator = (self.T * self.Z).double();
48+
let x_denom = yy - axx;
49+
50+
// Compute y
51+
let y_numerator = yy_plus_axx;
52+
let y_denom = self.Z.square().double() - yy_plus_axx;
53+
54+
let X = x_numerator * y_denom;
55+
let Y = y_numerator * x_denom;
56+
let T = x_numerator * y_numerator;
57+
let Z = x_denom * y_denom;
58+
59+
Self { X, Y, T, Z }
60+
}
61+
}

ed448-goldilocks/src/curve/twedwards/extended.rs

Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#![allow(non_snake_case)]
22
#![allow(dead_code)]
33

4-
use crate::curve::twedwards::affine::AffinePoint;
5-
use crate::curve::twedwards::extensible::ExtensiblePoint;
4+
use super::IsogenyMap;
5+
use super::affine::AffinePoint;
6+
use super::extensible::ExtensiblePoint;
67
use crate::edwards::EdwardsPoint as EdwardsExtendedPoint;
78
use crate::field::FieldElement;
89
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
@@ -105,39 +106,16 @@ impl ExtendedPoint {
105106
}
106107

107108
/// Uses a 2-isogeny to map the point to the Ed448-Goldilocks
108-
// (2. Algorithm 2) https://eprint.iacr.org/2008/522.pdf
109109
pub fn to_untwisted(self) -> EdwardsExtendedPoint {
110-
// x = 2xy / (y^2 + a*x^2)
111-
// y = (y^2 - a*x^2) / (2 - y^2 - a*x^2)
112-
113-
// Convert to affine now, then derive extended version later
114-
let affine = self.to_affine();
115-
let x = affine.x;
116-
let y = affine.y;
117-
118-
let yy = y.square();
119-
let xx = x.square();
120-
let axx = -xx;
121-
let yy_plus_axx = yy + axx;
122-
123-
// Compute x
124-
let x_numerator = (x * y).double();
125-
let x_denom = yy - axx;
126-
127-
// Compute y
128-
let y_numerator = yy_plus_axx;
129-
let y_denom = FieldElement::TWO - yy_plus_axx;
130-
131-
let common_denom = (x_denom * y_denom).invert();
132-
let new_x = x_numerator * y_denom * common_denom;
133-
let new_y = y_numerator * x_denom * common_denom;
134-
135-
EdwardsExtendedPoint {
136-
X: new_x,
137-
Y: new_y,
138-
Z: FieldElement::ONE,
139-
T: new_x * new_y,
110+
let IsogenyMap { X, Y, T, Z } = IsogenyMap {
111+
X: self.X,
112+
Y: self.Y,
113+
T: self.T,
114+
Z: self.Z,
140115
}
116+
.map(|f| -f);
117+
118+
EdwardsExtendedPoint { X, Y, Z, T }
141119
}
142120

143121
/// Checks if the point is on the curve

ed448-goldilocks/src/edwards/extended.rs

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use core::iter::Sum;
44
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
55

66
use crate::curve::scalar_mul::variable_base;
7+
use crate::curve::twedwards::IsogenyMap;
78
use crate::curve::twedwards::extended::ExtendedPoint as TwistedExtendedPoint;
89
use crate::field::FieldElement;
910
use crate::*;
@@ -669,29 +670,16 @@ impl EdwardsPoint {
669670
AffinePoint { x, y }
670671
}
671672

672-
// Copied from https://github.com/otrv4/libgoldilocks/blob/d07cb5b423995bae1155702aa949846c95d855c1/src/goldilocks.c#L980-L994.
673673
pub(crate) fn to_twisted(self) -> TwistedExtendedPoint {
674-
let c = self.X.square();
675-
let a = self.Y.square();
676-
let d = c + a;
677-
let t = self.Y + self.X;
678-
let b = t.square();
679-
let b = b - d;
680-
let t = a - c;
681-
let x = self.Z.square();
682-
let z = x.double();
683-
let a = z - d;
684-
let new_x = a * b;
685-
let new_z = t * a;
686-
let new_y = t * d;
687-
let new_t = b * d;
688-
689-
TwistedExtendedPoint {
690-
X: new_x,
691-
Y: new_y,
692-
Z: new_z,
693-
T: new_t,
674+
let IsogenyMap { X, Y, T, Z } = IsogenyMap {
675+
X: self.X,
676+
Y: self.Y,
677+
T: self.T,
678+
Z: self.Z,
694679
}
680+
.map(|f| f);
681+
682+
TwistedExtendedPoint { X, Y, Z, T }
695683
}
696684

697685
/// Compute the negation of this point's `x`-coordinate.

0 commit comments

Comments
 (0)