From 3fda00706c660ed400bffc86c7f23f325911cb06 Mon Sep 17 00:00:00 2001 From: Markus Rudy Date: Fri, 11 Oct 2024 22:59:05 +0200 Subject: [PATCH] wip: rust cli --- rust/Cargo.lock | 200 ++++++++++++++++++++++++++++++++++++++++++++ rust/Cargo.toml | 12 +++ rust/src/cli/bin.rs | 81 ++++++++++++++++++ 3 files changed, 293 insertions(+) create mode 100644 rust/src/cli/bin.rs diff --git a/rust/Cargo.lock b/rust/Cargo.lock index fc2995e..a1ebff1 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -2,6 +2,61 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "bitflags" version = "2.5.0" @@ -29,6 +84,52 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + [[package]] name = "cpufeatures" version = "0.2.12" @@ -131,6 +232,8 @@ dependencies = [ name = "glome" version = "0.1.0" dependencies = [ + "base64", + "clap", "hex-literal", "hmac", "openssl", @@ -138,6 +241,12 @@ dependencies = [ "x25519-dalek", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hex-literal" version = "0.3.4" @@ -153,6 +262,12 @@ dependencies = [ "digest", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "libc" version = "0.2.154" @@ -282,6 +397,12 @@ dependencies = [ "digest", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subtle" version = "2.5.0" @@ -311,6 +432,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "vcpkg" version = "0.2.15" @@ -329,6 +456,79 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "x25519-dalek" version = "2.0.1" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 11988aa..fd19679 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -7,13 +7,19 @@ edition = "2021" default = [ "dalek" ] dalek = [ "dep:x25519-dalek" ] openssl = [ "dep:openssl" ] +cli = [ "dep:base64", "dep:clap" ] [dependencies] +# lib sha2 = "0.10" hmac = "0.12" x25519-dalek = { version = "2.0", features = ["getrandom", "static_secrets"], optional = true } openssl = { version = "0.10", optional = true } +# cli +base64 = { version = "0.21", optional = true } +clap = { version = "4", features = ["derive"], optional = true} + [dev-dependencies] # test hex-literal = "0.3" @@ -21,3 +27,9 @@ hex-literal = "0.3" [lib] name = "glome" path = "src/lib.rs" + +[[bin]] +name = "glome" +path = "src/cli/bin.rs" + +required-features = ["cli"] diff --git a/rust/src/cli/bin.rs b/rust/src/cli/bin.rs new file mode 100644 index 0000000..4196f68 --- /dev/null +++ b/rust/src/cli/bin.rs @@ -0,0 +1,81 @@ +use base64::{engine::general_purpose, Engine as _}; +use clap::{Args, Parser, Subcommand}; +use x25519_dalek::{StaticSecret, PublicKey}; +use std::convert::TryInto; +use std::fs; +use std::io::{self, Read, Write}; +use std::path::PathBuf; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct Cli { + #[command(subcommand)] + command: Glome, +} + +#[derive(Args)] +struct TagArgs { + /// Path to secret key + #[arg(short, long, value_name = "FILE")] + key: PathBuf, + /// Path to peer's public key + #[arg(short, long, value_name = "FILE")] + peer: PathBuf, + /// Message counter index + #[arg(short, long, value_name = "n")] + counter: Option, +} + +#[derive(Subcommand)] +enum Glome { + /// Generate a new secret key and print it to stdout + Genkey, + /// Read a private key from stdin and write its public key to stdout + Pubkey, + /// Tag a message read from stdin + Tag(TagArgs), +} + +fn genkey() -> io::Result<()> { + io::stdout().write_all(StaticSecret::random().as_bytes()) +} + +// TODO(burgerdev): this is the pre-0.1.0 way of writing public keys! +fn pubkey() -> io::Result<()> { + let mut buf: [u8; 32] = [0; 32]; + io::stdin().read_exact(&mut buf)?; + let sk: StaticSecret = buf.into(); + let pk: PublicKey = (&sk).into(); + io::stdout().write_all(pk.as_bytes()) +} + +fn read_key(path: &PathBuf) -> [u8; 32] { + let b: Box<[u8; 32]> = fs::read(path) + .expect(format!("file {:?} should be readable", path).as_str()) + .into_boxed_slice() + .try_into() + .expect(format!("file {:?} should contain exactly 32 bytes", path).as_str()); + *b +} + +fn gentag(args: &TagArgs) -> io::Result<()> { + let ours: StaticSecret = read_key(&args.key).into(); + let theirs: PublicKey = read_key(&args.peer).into(); + + let mut buf = Vec::new(); + io::stdin().read_to_end(&mut buf)?; + + let t = glome::tag(&ours, &theirs, args.counter.unwrap_or_default() /* TODO */, &buf); + + let encoded = general_purpose::URL_SAFE.encode(&t); + + io::stdout().write_all(encoded.as_bytes()) +} + +fn main() -> io::Result<()> { + match &Cli::parse().command { + Glome::Genkey => genkey(), + Glome::Pubkey => pubkey(), + Glome::Tag(tag_args) => gentag(tag_args), + } +}