curve25519-dalek-source/tests/x25519.rs
Tony Arcieri c8c9f29989
Add Scalar and MontgomeryPoint conversions (#296)
* Add `Scalar` and `MontgomeryPoint` conversions

- Adds `SigningKey::to_scalar` to extract the private scalar
- Adds `VerifyingKey::to_montgomery` to map the verifying key's
  `EdwardsPoint` to a `MontgomeryPoint`
- Also adds corresponding `From<&T>` impls which call the inherent
  methods.

This is useful for systems which are keyed using Ed25519 keys which
would like to use X25519 for D-H. Having inherent methods means it's
possible to call these methods without having to import `Scalar` and
`MontgomeryPoint` from `curve25519-dalek`.

This is of course a bit circuitous: we could just multiply `Scalar` by
`EdwardsPoint` and use the resulting `EdwardsPoint` as the D-H shared
secret, however it seems many protocols have adopted this approach of
mapping to `MontgomeryPoint` and using that for the shared secret, since
X25519 is traditionally used for ECDH with Curve25519.

* Add reference to eprint 2021/509

* Basic X25519 Diffie-Hellman test
2023-03-30 13:29:36 -04:00

54 lines
1.9 KiB
Rust

//! Tests for converting Ed25519 keys into X25519 (Montgomery form) keys.
use ed25519_dalek::SigningKey;
use hex_literal::hex;
/// Tests that X25519 Diffie-Hellman works when using keys converted from Ed25519.
// TODO: generate test vectors using another implementation of Ed25519->X25519
#[test]
fn ed25519_to_x25519_dh() {
// Keys from RFC8032 test vectors (from section 7.1)
let ed25519_secret_key_a =
hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60");
let ed25519_secret_key_b =
hex!("4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb");
let ed25519_signing_key_a = SigningKey::from_bytes(&ed25519_secret_key_a);
let ed25519_signing_key_b = SigningKey::from_bytes(&ed25519_secret_key_b);
let scalar_a = ed25519_signing_key_a.to_scalar();
let scalar_b = ed25519_signing_key_b.to_scalar();
assert_eq!(
scalar_a.to_bytes(),
hex!("307c83864f2833cb427a2ef1c00a013cfdff2768d980c0a3a520f006904de94f")
);
assert_eq!(
scalar_b.to_bytes(),
hex!("68bd9ed75882d52815a97585caf4790a7f6c6b3b7f821c5e259a24b02e502e51")
);
let x25519_public_key_a = ed25519_signing_key_a.verifying_key().to_montgomery();
let x25519_public_key_b = ed25519_signing_key_b.verifying_key().to_montgomery();
assert_eq!(
x25519_public_key_a.to_bytes(),
hex!("d85e07ec22b0ad881537c2f44d662d1a143cf830c57aca4305d85c7a90f6b62e")
);
assert_eq!(
x25519_public_key_b.to_bytes(),
hex!("25c704c594b88afc00a76b69d1ed2b984d7e22550f3ed0802d04fbcd07d38d47")
);
let expected_shared_secret =
hex!("5166f24a6918368e2af831a4affadd97af0ac326bdf143596c045967cc00230e");
assert_eq!(
(x25519_public_key_a * scalar_b).to_bytes(),
expected_shared_secret
);
assert_eq!(
(x25519_public_key_b * scalar_a).to_bytes(),
expected_shared_secret
);
}