diff --git a/Cargo.lock b/Cargo.lock index 71f71b5..a1ce26b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,6 +68,7 @@ name = "azirevpn" version = "0.2.0" dependencies = [ "anyhow", + "base64 0.21.0", "clap", "directories", "env_logger", @@ -79,6 +80,7 @@ dependencies = [ "serde", "serde_json", "ureq", + "x25519-dalek", ] [[package]] @@ -87,6 +89,12 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" + [[package]] name = "bitflags" version = "1.3.2" @@ -177,6 +185,20 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "curve25519-dalek" +version = "4.0.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d928d978dbec61a1167414f5ec534f24bea0d7a0d24dd9b6233d3d8223e585" +dependencies = [ + "cfg-if", + "fiat-crypto", + "packed_simd_2", + "platforms", + "subtle", + "zeroize", +] + [[package]] name = "directories" version = "5.0.0" @@ -231,6 +253,12 @@ dependencies = [ "libc", ] +[[package]] +name = "fiat-crypto" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" + [[package]] name = "flate2" version = "1.0.25" @@ -349,6 +377,12 @@ version = "0.2.141" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +[[package]] +name = "libm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" + [[package]] name = "linux-raw-sys" version = "0.3.1" @@ -391,12 +425,28 @@ version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +[[package]] +name = "packed_simd_2" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282" +dependencies = [ + "cfg-if", + "libm", +] + [[package]] name = "percent-encoding" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +[[package]] +name = "platforms" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" + [[package]] name = "proc-macro2" version = "1.0.56" @@ -415,6 +465,15 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -552,6 +611,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + [[package]] name = "syn" version = "1.0.109" @@ -651,7 +716,7 @@ version = "2.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "338b31dd1314f68f3aabf3ed57ab922df95ffcd902476ca7ba3c4ce7b908c46d" dependencies = [ - "base64", + "base64 0.13.1", "flate2", "log", "once_cell", @@ -946,3 +1011,35 @@ name = "windows_x86_64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "x25519-dalek" +version = "2.0.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabd6e16dd08033932fc3265ad4510cc2eab24656058a6dcb107ffe274abcc95" +dependencies = [ + "curve25519-dalek", + "rand_core", + "serde", + "zeroize", +] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +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 2.0.13", +] diff --git a/Cargo.toml b/Cargo.toml index 9869705..fc42b7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ license = "MIT" [dependencies] anyhow = "1.0.65" +base64 = "0.21.0" clap = { version = "4.0.0", features = ["derive"] } directories = "5.0.0" env_logger = "0.10.0" @@ -20,3 +21,4 @@ once_cell = "1.17.1" serde = { version = "1.0.145", features = ["derive"] } serde_json = "1.0.85" ureq = { version = "2.5.0", features = ["json"] } +x25519-dalek = { version = "2.0.0-rc.2", features = ["getrandom", "static_secrets"] } diff --git a/src/keys.rs b/src/keys.rs index a3a2b84..eb0036e 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -1,12 +1,14 @@ +use base64::prelude::{Engine as _, BASE64_STANDARD}; use gethostname::gethostname; use log::debug; -use std::io::Write; +use x25519_dalek::{PublicKey, StaticSecret}; use std::path::PathBuf; -use std::process; use crate::dirs::get_data_dir; +const KEY_SIZE: usize = 32; + #[derive(Debug)] pub(crate) struct WireguardKeyPair { pub public_key: String, @@ -47,21 +49,16 @@ pub(crate) fn get_keys(machine: Option<&PathBuf>) -> Result anyhow::Result { - let privkey = process::Command::new("wg").arg("genkey").output()?.stdout; - Ok(String::from_utf8(privkey)?.trim_end().to_string()) + let private_key = StaticSecret::random(); + Ok(BASE64_STANDARD.encode(private_key.to_bytes())) } fn generate_public_key(private_key: &str) -> anyhow::Result { - let mut pubkey_cmd = process::Command::new("wg") - .arg("pubkey") - .stdin(process::Stdio::piped()) - .stdout(process::Stdio::piped()) - .spawn()?; - pubkey_cmd - .stdin - .as_mut() - .expect("no stdin") - .write_all(private_key.as_bytes())?; - let pubkey = pubkey_cmd.wait_with_output()?.stdout; - Ok(String::from_utf8(pubkey)?.trim_end().to_string()) + let mut key_data = [0u8; KEY_SIZE]; + let key_bytes = BASE64_STANDARD.decode(private_key)?; + assert_eq!(key_bytes.len(), KEY_SIZE); + key_data[0..KEY_SIZE].copy_from_slice(&key_bytes); + let key = StaticSecret::from(key_data); + let pubkey = PublicKey::from(&key); + Ok(BASE64_STANDARD.encode(pubkey.to_bytes())) }