-
Notifications
You must be signed in to change notification settings - Fork 478
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ed: Brought back to_scalar_bytes; added regression test
- Loading branch information
Showing
2 changed files
with
38 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,65 @@ | ||
//! Tests for converting Ed25519 keys into X25519 (Montgomery form) keys. | ||
use curve25519_dalek::scalar::{clamp_integer, Scalar}; | ||
use ed25519_dalek::SigningKey; | ||
use hex_literal::hex; | ||
use sha2::{Digest, Sha512}; | ||
|
||
/// Helper function to return the bytes corresponding to the input bytes after being clamped and | ||
/// reduced mod 2^255 - 19 | ||
fn clamp_and_reduce(bytes: &[u8]) -> [u8; 32] { | ||
assert_eq!(bytes.len(), 32); | ||
Scalar::from_bytes_mod_order(clamp_integer(bytes.try_into().unwrap())).to_bytes() | ||
} | ||
use x25519_dalek::{PublicKey as XPublicKey, StaticSecret as XStaticSecret}; | ||
|
||
/// 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 ed_secret_key_a = hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"); | ||
let ed_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 ed_signing_key_a = SigningKey::from_bytes(&ed_secret_key_a); | ||
let ed_signing_key_b = SigningKey::from_bytes(&ed_secret_key_b); | ||
|
||
let scalar_a = ed25519_signing_key_a.to_scalar(); | ||
let scalar_b = ed25519_signing_key_b.to_scalar(); | ||
// Create an x25519 static secret from the ed25519 signing key | ||
let scalar_bytes_a = ed_signing_key_a.to_scalar_bytes(); | ||
let scalar_bytes_b = ed_signing_key_b.to_scalar_bytes(); | ||
let x_static_secret_a = XStaticSecret::from(scalar_bytes_a); | ||
let x_static_secret_b = XStaticSecret::from(scalar_bytes_b); | ||
|
||
// Compare the scalar bytes to the first 32 bytes of SHA-512(secret_key). We have to clamp and | ||
// reduce the SHA-512 output because that's what the spec does before using the scalars for | ||
// anything. | ||
assert_eq!(scalar_bytes_a, &Sha512::digest(ed_secret_key_a)[..32],); | ||
assert_eq!(scalar_bytes_b, &Sha512::digest(ed_secret_key_b)[..32],); | ||
|
||
let x_public_key_a = XPublicKey::from(&x_static_secret_a); | ||
let x_public_key_b = XPublicKey::from(&x_static_secret_b); | ||
assert_eq!( | ||
scalar_a.to_bytes(), | ||
clamp_and_reduce(&Sha512::digest(ed25519_secret_key_a)[..32]), | ||
x_public_key_a.to_bytes(), | ||
hex!("d85e07ec22b0ad881537c2f44d662d1a143cf830c57aca4305d85c7a90f6b62e") | ||
); | ||
assert_eq!( | ||
scalar_b.to_bytes(), | ||
clamp_and_reduce(&Sha512::digest(ed25519_secret_key_b)[..32]), | ||
x_public_key_b.to_bytes(), | ||
hex!("25c704c594b88afc00a76b69d1ed2b984d7e22550f3ed0802d04fbcd07d38d47") | ||
); | ||
|
||
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(); | ||
|
||
// Test the claim made in the comments of SigningKey::to_scalar_bytes, i.e., that the resulting | ||
// scalar is a valid private key for the x25519 pubkey represented by | ||
// `sk.verifying_key().to_montgomery()` | ||
assert_eq!( | ||
x25519_public_key_a.to_bytes(), | ||
hex!("d85e07ec22b0ad881537c2f44d662d1a143cf830c57aca4305d85c7a90f6b62e") | ||
ed_signing_key_a.verifying_key().to_montgomery().as_bytes(), | ||
x_public_key_a.as_bytes() | ||
); | ||
assert_eq!( | ||
x25519_public_key_b.to_bytes(), | ||
hex!("25c704c594b88afc00a76b69d1ed2b984d7e22550f3ed0802d04fbcd07d38d47") | ||
ed_signing_key_b.verifying_key().to_montgomery().as_bytes(), | ||
x_public_key_b.as_bytes() | ||
); | ||
|
||
// Check that Diffie-Hellman works | ||
let expected_shared_secret = | ||
hex!("5166f24a6918368e2af831a4affadd97af0ac326bdf143596c045967cc00230e"); | ||
|
||
assert_eq!( | ||
(x25519_public_key_a * scalar_b).to_bytes(), | ||
expected_shared_secret | ||
x_static_secret_a.diffie_hellman(&x_public_key_b).to_bytes(), | ||
expected_shared_secret, | ||
); | ||
assert_eq!( | ||
(x25519_public_key_b * scalar_a).to_bytes(), | ||
expected_shared_secret | ||
x_static_secret_b.diffie_hellman(&x_public_key_a).to_bytes(), | ||
expected_shared_secret, | ||
); | ||
} |