Skip to content

Commit cf790a0

Browse files
committed
Optimize Edwards to Montgomery conversions
1 parent 6ff0824 commit cf790a0

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

ed448-goldilocks/src/edwards/affine.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,18 @@ impl AffinePoint {
154154
}
155155
}
156156

157+
/// Convert this point to [`MontgomeryPoint`]
158+
// See https://www.rfc-editor.org/rfc/rfc7748#section-4.2 4-isogeny maps
159+
pub fn to_montgomery(&self) -> MontgomeryPoint {
160+
// u = y^2/x^2
161+
162+
// Simplified to:
163+
// u = (y/x)^2
164+
let u = (self.y * self.x.invert()).square();
165+
166+
MontgomeryPoint(u.to_bytes())
167+
}
168+
157169
/// The X coordinate
158170
pub fn x(&self) -> [u8; 56] {
159171
self.x.to_bytes()

ed448-goldilocks/src/edwards/extended.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -318,16 +318,19 @@ impl EdwardsPoint {
318318
};
319319

320320
/// Convert this point to [`MontgomeryPoint`]
321+
// See https://www.rfc-editor.org/rfc/rfc7748#section-4.2 4-isogeny maps
321322
pub fn to_montgomery(&self) -> MontgomeryPoint {
322-
// u = y^2 * [(1-dy^2)/(1-y^2)]
323+
// Affine map:
324+
// (x, y) = (x/z, y/z)
325+
// Edwards to montgomery:
326+
// u = y^2/x^2
323327

324-
let affine = self.to_affine();
325-
326-
let yy = affine.y.square();
327-
let dyy = FieldElement::EDWARDS_D * yy;
328-
329-
let u = yy * (FieldElement::ONE - dyy) * (FieldElement::ONE - yy).invert();
328+
// Simplified to:
329+
// u = (y/z)^2/(x/z)^2
330+
// u = ((y/z)/(x/z))^2
331+
// u = (y/x)^2
330332

333+
let u = (self.Y * self.X.invert()).square();
331334
MontgomeryPoint(u.to_bytes())
332335
}
333336

ed448-goldilocks/src/montgomery.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,4 +237,18 @@ mod tests {
237237
let goldilocks_point = bp.scalar_mul(&scalar);
238238
assert_eq!(goldilocks_point.to_montgomery(), montgomery_res);
239239
}
240+
241+
#[test]
242+
fn test_montgomery_edwards_affine() {
243+
let scalar = EdwardsScalar::from(200u32);
244+
use crate::GOLDILOCKS_BASE_POINT as bp;
245+
246+
// Montgomery scalar mul
247+
let montgomery_bp = bp.to_affine().to_montgomery();
248+
let montgomery_res = &montgomery_bp * &scalar;
249+
250+
// Goldilocks scalar mul
251+
let goldilocks_point = bp.scalar_mul(&scalar).to_affine();
252+
assert_eq!(goldilocks_point.to_montgomery(), montgomery_res);
253+
}
240254
}

0 commit comments

Comments
 (0)