diff --git a/ed448-goldilocks/src/edwards/affine.rs b/ed448-goldilocks/src/edwards/affine.rs index 68f44931a..1ac2981af 100644 --- a/ed448-goldilocks/src/edwards/affine.rs +++ b/ed448-goldilocks/src/edwards/affine.rs @@ -110,6 +110,18 @@ impl AffinePoint { } } + /// Convert this point to [`MontgomeryPoint`] + // See https://www.rfc-editor.org/rfc/rfc7748#section-4.2 4-isogeny maps + pub fn to_montgomery(&self) -> MontgomeryPoint { + // u = y^2/x^2 + + // Simplified to: + // u = (y/x)^2 + let u = (self.y * self.x.invert()).square(); + + MontgomeryPoint(u.to_bytes()) + } + /// The X coordinate pub fn x(&self) -> [u8; 56] { self.x.to_bytes() diff --git a/ed448-goldilocks/src/edwards/extended.rs b/ed448-goldilocks/src/edwards/extended.rs index 104d35eb7..79a2304bf 100644 --- a/ed448-goldilocks/src/edwards/extended.rs +++ b/ed448-goldilocks/src/edwards/extended.rs @@ -529,16 +529,19 @@ impl EdwardsPoint { }; /// Convert this point to [`MontgomeryPoint`] + // See https://www.rfc-editor.org/rfc/rfc7748#section-4.2 4-isogeny maps pub fn to_montgomery(&self) -> MontgomeryPoint { - // u = y^2 * [(1-dy^2)/(1-y^2)] + // Affine map: + // (x, y) = (x/z, y/z) + // Edwards to montgomery: + // u = y^2/x^2 - let affine = self.to_affine(); - - let yy = affine.y.square(); - let dyy = FieldElement::EDWARDS_D * yy; - - let u = yy * (FieldElement::ONE - dyy) * (FieldElement::ONE - yy).invert(); + // Simplified to: + // u = (y/z)^2/(x/z)^2 + // u = ((y/z)/(x/z))^2 + // u = (y/x)^2 + let u = (self.Y * self.X.invert()).square(); MontgomeryPoint(u.to_bytes()) } diff --git a/ed448-goldilocks/src/montgomery.rs b/ed448-goldilocks/src/montgomery.rs index 5c4df6c6d..def8a5e39 100644 --- a/ed448-goldilocks/src/montgomery.rs +++ b/ed448-goldilocks/src/montgomery.rs @@ -233,4 +233,18 @@ mod tests { let goldilocks_point = bp.scalar_mul(&scalar); assert_eq!(goldilocks_point.to_montgomery(), montgomery_res); } + + #[test] + fn test_montgomery_edwards_affine() { + let scalar = EdwardsScalar::from(200u32); + use crate::GOLDILOCKS_BASE_POINT as bp; + + // Montgomery scalar mul + let montgomery_bp = bp.to_affine().to_montgomery(); + let montgomery_res = &montgomery_bp * &scalar; + + // Goldilocks scalar mul + let goldilocks_point = bp.scalar_mul(&scalar).to_affine(); + assert_eq!(goldilocks_point.to_montgomery(), montgomery_res); + } }