From eb77dad57f8d02551d7dfb62bf50c1c9006bb68b Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Mon, 18 Dec 2023 11:39:09 -0500 Subject: [PATCH] `ed`: `puck` --- rust/ares_crypto/Cargo.lock | 77 ++++++++++++++++++++++++++ rust/ares_crypto/Cargo.toml | 8 ++- rust/ares_crypto/src/aes_siv.rs | 6 +- rust/ares_crypto/src/ed25519.rs | 98 ++++++++++++++++++++++++--------- 4 files changed, 156 insertions(+), 33 deletions(-) diff --git a/rust/ares_crypto/Cargo.lock b/rust/ares_crypto/Cargo.lock index a1bc465..775b05a 100644 --- a/rust/ares_crypto/Cargo.lock +++ b/rust/ares_crypto/Cargo.lock @@ -57,8 +57,11 @@ dependencies = [ "assert_no_alloc", "ed25519", "ed25519-dalek", + "ibig", "rand", + "sha2", "urcrypt-sys", + "x25519-dalek", ] [[package]] @@ -234,6 +237,7 @@ dependencies = [ "platforms", "rustc_version", "subtle", + "zeroize", ] [[package]] @@ -380,6 +384,18 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "ibig" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1fcc7f316b2c079dde77564a1360639c1a956a23fa96122732e416cb10717bb" +dependencies = [ + "cfg-if", + "num-traits", + "rand", + "static_assertions", +] + [[package]] name = "inout" version = "0.1.3" @@ -461,6 +477,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.19.0" @@ -627,6 +652,26 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "sha2" version = "0.10.8" @@ -678,6 +723,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "subtle" version = "2.5.0" @@ -829,8 +880,34 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +[[package]] +name = "x25519-dalek" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96" +dependencies = [ + "curve25519-dalek", + "rand_core", + "serde", + "zeroize", +] + [[package]] name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/rust/ares_crypto/Cargo.toml b/rust/ares_crypto/Cargo.toml index 502e595..a722c3f 100644 --- a/rust/ares_crypto/Cargo.toml +++ b/rust/ares_crypto/Cargo.toml @@ -12,11 +12,15 @@ assert_no_alloc = "1.1.2" aes-siv = { version = "0.7.0", features = ["heapless"], default-features = false } ed25519-dalek = { version = "2.1.0", features = ["pkcs8", "rand_core"], default-features = false } ed25519 = { version = "2.2.3" } -rand = { version = "0.8.5", features = ["getrandom", "std_rng"], default-features = false } +rand = { version = "0.8.5", features = ["std_rng"], default-features = false } urcrypt-sys = { version = "0.1.1", optional = true } +sha2 = "0.10.8" +ibig = "0.3.6" +x25519-dalek = "2.0.0" [features] -default = ["aes_siv", "ed25519"] +# XX turn off test_vs_urcrypt after development +default = ["aes_siv", "ed25519", "test_vs_urcrypt"] aes_siv = [] ed25519 = [] test_vs_urcrypt = ["urcrypt-sys"] diff --git a/rust/ares_crypto/src/aes_siv.rs b/rust/ares_crypto/src/aes_siv.rs index 5aa0639..a2b310c 100644 --- a/rust/ares_crypto/src/aes_siv.rs +++ b/rust/ares_crypto/src/aes_siv.rs @@ -1,8 +1,4 @@ -use aes_siv::{ - aead::{heapless::Vec, AeadInPlace, Error, KeyInit}, - Aes256SivAead, - Nonce, // Or `Aes128SivAead` -}; +use aes_siv::aead::Error; pub fn _ac_aes_siv_en() -> Result<(), Error> { todo!(); diff --git a/rust/ares_crypto/src/ed25519.rs b/rust/ares_crypto/src/ed25519.rs index e7b43e2..eee8f1c 100644 --- a/rust/ares_crypto/src/ed25519.rs +++ b/rust/ares_crypto/src/ed25519.rs @@ -1,38 +1,84 @@ -use std::ptr::copy_nonoverlapping; - -use ed25519_dalek::{SignatureError, SigningKey}; use rand::{rngs::StdRng, SeedableRng}; +use ed25519_dalek::{SigningKey, VerifyingKey}; +use x25519_dalek::{EphemeralSecret, PublicKey, SharedSecret}; -/// Generate a public key from the given seed and write it to the given 32-byte output buffer, -pub fn ac_ed_puck(seed: &mut [u8; 32], out: *mut u8) -> Result<(), SignatureError> { - let mut csprng = StdRng::from_seed(*seed); - let signing_key = SigningKey::generate(&mut csprng); +/// Generate a public key from the given seed and write it to the given output slice. +pub fn ac_ed_puck(seed: &mut [u8; 32], out: &mut [u8; 32]) { + let signing_key = SigningKey::from_bytes(seed); let verifying_key = signing_key.verifying_key(); - unsafe { - copy_nonoverlapping(verifying_key.as_bytes().as_ptr(), out, 32); - } - Ok(()) + *out = verifying_key.to_bytes(); } -/// Perform a key exchange between the given public key and the keypair generated from the given seed, -/// writing the resulting shared key to the given 32-byte output buffer. -pub fn ac_ed_shar(public: &[u8; 32], seed: &[u8; 32], out: *mut u8) -> Result<(), SignatureError> { - // Generate a keypair from the given seed. - let mut csprng = StdRng::from_seed(*seed); - let self_key = SigningKey::generate(&mut csprng); +/// Perform a key exchange between the given public key and the private key of +/// the keypair generate from the given seed, writing the resulting shared key +/// to the given output slice. +pub fn ac_ed_shar(public: &[u8; 32], seed: &[u8; 32], out: &mut [u8; 32]) { + // let self_key = SigningKey::from_bytes(seed); - let mut keypair_bytes = [0u8; 64]; - keypair_bytes[..32].copy_from_slice(&self_key.to_bytes()); - keypair_bytes[32..].copy_from_slice(public); - let shared_key = SigningKey::from_keypair_bytes(&keypair_bytes)?; - unsafe { - copy_nonoverlapping(shared_key.to_bytes().as_ptr(), out, 32); + // let other_key = PublicKey::from(*public); + // let shared_secret = self_key.diffie_hellman(&other_key); + // *out = shared_secret.to_bytes(); +} + +#[cfg(test)] +mod tests { + use super::ac_ed_puck; + + #[test] + fn test_ed_puck() { + let mut seed: [u8; 32] = [0; 32]; + let mut public_key: [u8; 32] = [0; 32]; + ac_ed_puck(&mut seed, &mut public_key); + assert_eq!( + public_key, + [ + 59, 106, 39, 188, 206, 182, 164, 45, 98, 163, 168, 208, 42, 111, 13, 115, 101, 50, + 21, 119, 29, 226, 67, 166, 58, 192, 72, 161, 139, 89, 218, 41 + ] + ); } - Ok(()) } #[cfg(test)] #[cfg(feature = "test_vs_urcrypt")] -mod ucrypt_test { - // tests comparing urcrypt and ares_crypto output for ed25519 functions go here +mod ucrypt_tests { + use super::{ac_ed_puck, ac_ed_shar}; + use ibig::ubig; + use urcrypt_sys::{urcrypt_ed_puck, urcrypt_ed_shar}; + + #[test] + fn test_ed_puck() { + let mut seed: [u8; 32] = [0; 32]; + + let mut uc_out: [u8; 32] = [0; 32]; + unsafe { urcrypt_ed_puck(seed.as_ptr(), uc_out.as_mut_ptr()) }; + + let mut ac_out: [u8; 32] = [0; 32]; + ac_ed_puck(&mut seed, &mut ac_out); + + assert_eq!(ac_out, uc_out); + } + + #[test] + fn test_ed_shar() { + let seed_src = + &ubig!(_0x4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb) + .to_le_bytes(); + let mut seed: [u8; 32] = [0; 32]; + seed.copy_from_slice(seed_src); + + let public_key_src = + &ubig!(_0xd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a) + .to_le_bytes(); + let mut public_key: [u8; 32] = [0; 32]; + public_key.copy_from_slice(public_key_src); + + let mut uc_out: [u8; 32] = [0; 32]; + unsafe { urcrypt_ed_shar(public_key.as_ptr(), seed.as_ptr(), uc_out.as_mut_ptr()) }; + + let mut ac_out: [u8; 32] = [0; 32]; + ac_ed_shar(&public_key, &seed, &mut ac_out); + + assert_eq!(ac_out, uc_out); + } }