diff --git a/ed25519-dalek/src/verifying.rs b/ed25519-dalek/src/verifying.rs index b7e129788..b53032144 100644 --- a/ed25519-dalek/src/verifying.rs +++ b/ed25519-dalek/src/verifying.rs @@ -505,6 +505,11 @@ impl VerifyingKey { pub fn to_montgomery(&self) -> MontgomeryPoint { self.point.to_montgomery() } + + /// Return this verifying key in Edwards form. + pub fn to_edwards(&self) -> EdwardsPoint { + self.point + } } impl Verifier for VerifyingKey { @@ -563,6 +568,12 @@ impl TryFrom<&[u8]> for VerifyingKey { } } +impl From for EdwardsPoint { + fn from(vk: VerifyingKey) -> EdwardsPoint { + vk.point + } +} + #[cfg(all(feature = "alloc", feature = "pkcs8"))] impl pkcs8::EncodePublicKey for VerifyingKey { fn to_public_key_der(&self) -> pkcs8::spki::Result { diff --git a/ed25519-dalek/tests/ed25519.rs b/ed25519-dalek/tests/ed25519.rs index c05efa3c3..82ac33d76 100644 --- a/ed25519-dalek/tests/ed25519.rs +++ b/ed25519-dalek/tests/ed25519.rs @@ -459,6 +459,29 @@ mod integrations { assert_eq!(v, "Second public key"); assert_eq!(m.len(), 2usize); } + + #[test] + fn montgomery_and_edwards_conversion() { + let mut rng = rand::rngs::OsRng; + let signing_key = SigningKey::generate(&mut rng); + let verifying_key = signing_key.verifying_key(); + + let ed = verifying_key.to_edwards(); + + // Check that to_edwards and From return same result: + assert_eq!(ed, curve25519_dalek::EdwardsPoint::from(verifying_key)); + + // The verifying key serialization is simply the compressed Edwards point + assert_eq!(verifying_key.to_bytes(), ed.compress().0); + + // Check that modulo sign, to_montgomery().to_edwards() returns the original point + let monty = verifying_key.to_montgomery(); + let via_monty0 = monty.to_edwards(0).unwrap(); + let via_monty1 = monty.to_edwards(1).unwrap(); + + assert!(via_monty0 != via_monty1); + assert!(ed == via_monty0 || ed == via_monty1); + } } #[cfg(all(test, feature = "serde"))]