diff --git a/src/commands/init.rs b/src/commands/init.rs index 9bc9db962d..00af80c1f5 100644 --- a/src/commands/init.rs +++ b/src/commands/init.rs @@ -1,21 +1,20 @@ use crate::banner; use crate::identity::mixnet; +use crate::persistence::pathfinder::Pathfinder; use crate::persistence::pemstore::PemStore; use clap::ArgMatches; -use dirs; pub fn execute(matches: &ArgMatches) { println!("{}", banner()); println!("Initialising client..."); - let id = matches.value_of("id").unwrap(); // required for now - let os_config_dir = dirs::config_dir().unwrap(); // grabs the OS default config dir - let nym_client_config_dir = os_config_dir.join("nym").join("clients").join(id); + let id = matches.value_of("id").unwrap().to_string(); // required for now + let pathfinder = Pathfinder::new(id); - println!("Writing keypairs to {:?}...", nym_client_config_dir); + println!("Writing keypairs to {:?}...", pathfinder.config_dir); let mix_keys = mixnet::KeyPair::new(); - let pem_store = PemStore::new(); - pem_store.write(mix_keys, nym_client_config_dir); + let pem_store = PemStore::new(pathfinder); + pem_store.write(mix_keys); println!("Client configuration completed.\n\n\n") } diff --git a/src/commands/run.rs b/src/commands/run.rs index 0ce7a25f79..b7bec29923 100644 --- a/src/commands/run.rs +++ b/src/commands/run.rs @@ -1,5 +1,5 @@ use crate::clients::directory; -use crate::clients::directory::presence::{MixNodePresence, Topology}; +use crate::clients::directory::presence::Topology; use crate::clients::directory::requests::presence_topology_get::PresenceTopologyGetRequester; use crate::clients::directory::DirectoryClient; use crate::clients::mix::MixClient; @@ -15,10 +15,7 @@ use tokio::time::{interval_at, Instant}; pub fn execute(matches: &ArgMatches) { let custom_cfg = matches.value_of("customCfg"); - println!( - "Going to start client with custom config of: {:?}", - custom_cfg - ); + println!("Starting client with config: {:?}", custom_cfg); // Grab the network topology from the remote directory server let topology = get_topology(); diff --git a/src/identity/mixnet.rs b/src/identity/mixnet.rs index ae6a169d68..83507d7d70 100644 --- a/src/identity/mixnet.rs +++ b/src/identity/mixnet.rs @@ -1,6 +1,7 @@ use curve25519_dalek::montgomery::MontgomeryPoint; use curve25519_dalek::scalar::Scalar; +// This keypair serves as the user's identity within the Mixnet pub struct KeyPair { pub private: Scalar, pub public: MontgomeryPoint, @@ -12,6 +13,18 @@ impl KeyPair { KeyPair { private, public } } + pub fn from_bytes(private_bytes: Vec, public_bytes: Vec) -> KeyPair { + let mut bytes = [0; 32]; + bytes.copy_from_slice(&private_bytes[..]); + let private = Scalar::from_canonical_bytes(bytes).unwrap(); + + let mut bytes = [0; 32]; + bytes.copy_from_slice(&public_bytes[..]); + let public = MontgomeryPoint(bytes); + + KeyPair { private, public } + } + pub fn private_bytes(&self) -> Vec { self.private.to_bytes().to_vec() } diff --git a/src/persistence/mod.rs b/src/persistence/mod.rs index c21f39e57f..bc1ad593bd 100644 --- a/src/persistence/mod.rs +++ b/src/persistence/mod.rs @@ -1 +1,2 @@ +pub mod pathfinder; pub mod pemstore; diff --git a/src/persistence/pathfinder.rs b/src/persistence/pathfinder.rs new file mode 100644 index 0000000000..08110b9ae8 --- /dev/null +++ b/src/persistence/pathfinder.rs @@ -0,0 +1,21 @@ +use std::path::PathBuf; + +pub struct Pathfinder { + pub config_dir: PathBuf, + pub private_mix_key: PathBuf, + pub public_mix_key: PathBuf, +} + +impl Pathfinder { + pub fn new(id: String) -> Pathfinder { + let os_config_dir = dirs::config_dir().unwrap(); // grabs the OS default config dir + let config_dir = os_config_dir.join("nym").join("clients").join(id); + let private_mix_key = config_dir.join("private.pem"); + let public_mix_key = config_dir.join("public.pem"); + Pathfinder { + config_dir, + private_mix_key, + public_mix_key, + } + } +} diff --git a/src/persistence/pemstore.rs b/src/persistence/pemstore.rs index e8091f091e..0f367b48e7 100644 --- a/src/persistence/pemstore.rs +++ b/src/persistence/pemstore.rs @@ -1,41 +1,65 @@ use crate::identity::mixnet::KeyPair; -use pem::{encode, Pem}; +use crate::persistence::pathfinder::Pathfinder; +use pem::{encode, parse, Pem}; use std::fs::File; use std::io::prelude::*; use std::path::PathBuf; -pub struct PemStore {} +pub struct PemStore { + config_dir: PathBuf, + private_mix_key: PathBuf, + public_mix_key: PathBuf, +} impl PemStore { - pub fn new() -> PemStore { - PemStore {} + pub fn new(pathfinder: Pathfinder) -> PemStore { + PemStore { + config_dir: pathfinder.config_dir, + private_mix_key: pathfinder.private_mix_key, + public_mix_key: pathfinder.public_mix_key, + } } - pub fn write(&self, key_pair: KeyPair, path: PathBuf) { - std::fs::create_dir_all(path.clone()).unwrap(); + + pub fn read(&self) -> KeyPair { + let private = self.read_file(self.private_mix_key.clone()); + let public = self.read_file(self.public_mix_key.clone()); + + KeyPair::from_bytes(private, public) + } + + pub fn read_file(&self, filepath: PathBuf) -> Vec { + let mut pem_bytes = File::open(filepath).unwrap(); + let mut buf = Vec::new(); + pem_bytes.read_to_end(&mut buf).unwrap(); + let pem = parse(&buf).unwrap(); + pem.contents + } + // This should be refactored and made more generic for when we have other kinds of + // KeyPairs that we want to persist (e.g. validator keypairs, or keys for + // signing vs encryption). However, for the moment, it does the job. + pub fn write(&self, key_pair: KeyPair) { + std::fs::create_dir_all(self.config_dir.clone()).unwrap(); self.write_pem_file( - path.clone(), - String::from("private.pem"), + self.private_mix_key.clone(), key_pair.private_bytes(), String::from("SPHINX CURVE25519 PRIVATE KEY"), ); self.write_pem_file( - path.clone(), - String::from("public.pem"), + self.public_mix_key.clone(), key_pair.public_bytes(), String::from("SPHINX CURVE25519 PUBLIC KEY"), ); } - fn write_pem_file(&self, path: PathBuf, filename: String, data: Vec, tag: String) { + fn write_pem_file(&self, filepath: PathBuf, data: Vec, tag: String) { let pem = Pem { tag, contents: data, }; let key = encode(&pem); - let full_path = path.join(filename); - let mut file = File::create(full_path).unwrap(); + let mut file = File::create(filepath).unwrap(); file.write_all(key.as_bytes()).unwrap(); } }