diff --git a/services/identity/Cargo.lock b/services/identity/Cargo.lock --- a/services/identity/Cargo.lock +++ b/services/identity/Cargo.lock @@ -60,6 +60,17 @@ "syn", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -129,6 +140,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "3.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "535434c063ced786eb04aaf529308092c5ab60889e8fe24275d15de07b01fa97" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "lazy_static", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" +dependencies = [ + "heck 0.4.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -340,6 +390,12 @@ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -444,6 +500,7 @@ version = "0.1.0" dependencies = [ "argon2", + "clap", "curve25519-dalek", "digest 0.9.0", "futures-core", @@ -588,6 +645,12 @@ "zeroize", ] +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" + [[package]] name = "password-hash" version = "0.3.2" @@ -653,6 +716,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.36" @@ -679,7 +766,7 @@ checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ "bytes", - "heck", + "heck 0.3.3", "itertools", "lazy_static", "log", @@ -827,6 +914,12 @@ "winapi", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "subtle" version = "2.4.1" @@ -870,6 +963,21 @@ "winapi", ] +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + [[package]] name = "tokio" version = "1.17.0" @@ -1149,6 +1257,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/services/identity/Cargo.toml b/services/identity/Cargo.toml --- a/services/identity/Cargo.toml +++ b/services/identity/Cargo.toml @@ -3,8 +3,6 @@ version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] tonic = "0.6" prost = "0.9" @@ -15,6 +13,7 @@ curve25519-dalek = "3" sha2 = "0.9" digest = "0.9" +clap = { version = "3.1.12", features = ["derive"] } [build-dependencies] tonic-build = "0.6" diff --git a/services/identity/Dockerfile b/services/identity/Dockerfile --- a/services/identity/Dockerfile +++ b/services/identity/Dockerfile @@ -24,5 +24,6 @@ RUN rm ./target/release/deps/identity* RUN cargo build --release +RUN target/release/identity keygen -CMD ["./target/release/identity"] +CMD ["./target/release/identity", "server"] diff --git a/services/identity/src/keygen.rs b/services/identity/src/keygen.rs new file mode 100644 --- /dev/null +++ b/services/identity/src/keygen.rs @@ -0,0 +1,26 @@ +use crate::opaque::Cipher; +use opaque_ke::{ciphersuite::CipherSuite, rand::rngs::OsRng}; +use std::{env, fs, io}; + +const SECRETS_FILE_NAME: &str = "secret_key"; +const SECRETS_FILE_EXTENSION: &str = "txt"; + +pub fn generate_and_persist_keypair(dir: &str) -> Result<(), io::Error> { + let mut rng = OsRng; + let server_kp = Cipher::generate_random_keypair(&mut rng); + let mut path = env::current_dir()?; + path.push(dir); + if !path.exists() { + println!("Creating secrets directory {:?}", path); + fs::create_dir(&path)?; + } + path.push(SECRETS_FILE_NAME); + path.set_extension(SECRETS_FILE_EXTENSION); + if path.exists() { + println!("{:?} already exists", path); + return Ok(()); + } + println!("Writing secret key to {:?}", path); + fs::write(&path, server_kp.private().to_arr())?; + Ok(()) +} diff --git a/services/identity/src/main.rs b/services/identity/src/main.rs --- a/services/identity/src/main.rs +++ b/services/identity/src/main.rs @@ -1,19 +1,53 @@ +use clap::{Parser, Subcommand}; use tonic::transport::Server; +mod keygen; +mod opaque; mod service; + +use keygen::generate_and_persist_keypair; use service::{IdentityServiceServer, MyIdentityService}; const IDENTITY_SERVICE_SOCKET_ADDR: &str = "[::]:50051"; +const DEFAULT_SECRETS_DIRECTORY: &str = "secrets"; + +#[derive(Parser)] +#[clap(author, version, about, long_about = None)] +#[clap(propagate_version = true)] +struct Cli { + #[clap(subcommand)] + command: Commands, +} + +#[derive(Subcommand)] +enum Commands { + /// Runs the server + Server, + /// Generates and persists a keypair to use for PAKE registration and login + Keygen { + #[clap(short, long)] + #[clap(default_value_t = String::from(DEFAULT_SECRETS_DIRECTORY))] + dir: String, + }, +} #[tokio::main] async fn main() -> Result<(), Box> { - let addr = IDENTITY_SERVICE_SOCKET_ADDR.parse()?; - let identity_service = MyIdentityService::default(); + let cli = Cli::parse(); + match &cli.command { + Commands::Keygen { dir } => { + generate_and_persist_keypair(dir)?; + } + Commands::Server => { + let addr = IDENTITY_SERVICE_SOCKET_ADDR.parse()?; + let identity_service = MyIdentityService::default(); - Server::builder() - .add_service(IdentityServiceServer::new(identity_service)) - .serve(addr) - .await?; + Server::builder() + .add_service(IdentityServiceServer::new(identity_service)) + .serve(addr) + .await?; + } + } Ok(()) }