diff --git a/Cargo.lock b/Cargo.lock index c7cd0c9..804e41f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -211,8 +211,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.0.2" -source = "git+https://github.com/mcginty/curve25519-dalek?branch=main#2028ad6ee8783af2f260efb0390680f639c22c7e" +version = "4.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4033478fbf70d6acf2655ac70da91ee65852d69daf7a67bf7a2f518fb47aafcf" dependencies = [ "byteorder", "digest", @@ -1101,18 +1102,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "synstructure" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - [[package]] name = "tap" version = "1.0.1" @@ -1374,12 +1363,12 @@ name = "wgctrl" version = "1.4.1" dependencies = [ "base64", + "curve25519-dalek", "hex", "libc", "rand_core", "subtle", "wgctrl-sys", - "x25519-dalek", ] [[package]] @@ -1428,33 +1417,8 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" -[[package]] -name = "x25519-dalek" -version = "1.1.0" -source = "git+https://github.com/mcginty/x25519-dalek?branch=master#8edb77eda328f09f19f8ba9d33b114c5afafa457" -dependencies = [ - "curve25519-dalek", - "rand_core", - "zeroize", -] - [[package]] name = "zeroize" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "377db0846015f7ae377174787dd452e1c5f5a9050bc6f954911d01f116daa0cd" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2c1e130bebaeab2f23886bf9acbaca14b092408c452543c857f66399cd6dab1" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] diff --git a/wgctrl-rs/Cargo.toml b/wgctrl-rs/Cargo.toml index 06af954..57a7316 100644 --- a/wgctrl-rs/Cargo.toml +++ b/wgctrl-rs/Cargo.toml @@ -20,4 +20,4 @@ wgctrl-sys = { path = "../wgctrl-sys" } [target.'cfg(not(target_os = "linux"))'.dependencies] rand_core = "0.6" subtle = "2" -x25519-dalek = { git = "https://github.com/mcginty/x25519-dalek", branch = "master" } # pending https://github.com/dalek-cryptography/x25519-dalek/pull/64 +curve25519-dalek = "4.0.0-pre.1" diff --git a/wgctrl-rs/src/backends/userspace.rs b/wgctrl-rs/src/backends/userspace.rs index 5792d3f..f617938 100644 --- a/wgctrl-rs/src/backends/userspace.rs +++ b/wgctrl-rs/src/backends/userspace.rs @@ -1,3 +1,5 @@ +use curve25519_dalek::scalar::Scalar; + use crate::{Backend, Device, DeviceUpdate, InterfaceName, PeerConfig, PeerInfo, PeerStats}; #[cfg(target_os = "linux")] @@ -396,11 +398,16 @@ pub struct Key(pub [u8; 32]); impl Key { /// Generates and returns a new private key. pub fn generate_private() -> Self { - use rand_core::OsRng; - use x25519_dalek::StaticSecret; + use rand_core::{OsRng, RngCore}; - let key = StaticSecret::new(OsRng); - Self(key.to_bytes()) + let mut bytes = [0u8; 32]; + OsRng.fill_bytes(&mut bytes); + + // Apply key clamping. + bytes[0] &= 248; + bytes[31] &= 127; + bytes[31] |= 64; + Self(bytes) } /// Generates and returns a new preshared key. @@ -414,13 +421,12 @@ impl Key { /// Generates a public key for this private key. pub fn generate_public(&self) -> Self { - use x25519_dalek::{PublicKey, StaticSecret}; + use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE; - let mut public_bytes = [0u8; 32]; - let private_key = StaticSecret::from(self.0); - let public_key = PublicKey::from(&private_key); - public_bytes.copy_from_slice(public_key.as_bytes()); - Self(public_bytes) + // https://github.com/dalek-cryptography/x25519-dalek/blob/1c39ff92e0dfc0b24aa02d694f26f3b9539322a5/src/x25519.rs#L150 + let point = (&ED25519_BASEPOINT_TABLE * &Scalar::from_bits(self.0)).to_montgomery(); + + Self(point.to_bytes()) } /// Generates an all-zero key. @@ -466,3 +472,41 @@ impl Key { Ok(Self(sized_bytes)) } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_pubkey_generation() { + let privkey = "SGb+ojrRNDuMePufwtIYhXzA//k6wF3R21tEBgKlzlM="; + let pubkey = "DD5yKRfzExcV5+kDnTroDgCU15latdMjiQ59j1hEuk8="; + + let private = Key::from_base64(privkey).unwrap(); + let public = Key::generate_public(&private); + + assert_eq!(public.to_base64(), pubkey); + } + + #[test] + fn test_rng_sanity_private() { + let first = Key::generate_private(); + assert!(!first.is_zero()); + for _ in 0..100_000 { + let key = Key::generate_private(); + assert!(first != key); + assert!(!key.is_zero()); + } + } + + #[test] + fn test_rng_sanity_preshared() { + let first = Key::generate_preshared(); + assert!(!first.is_zero()); + for _ in 0..100_000 { + let key = Key::generate_preshared(); + assert!(first != key); + assert!(!key.is_zero()); + } + } +} \ No newline at end of file