Skip to content

Commit

Permalink
wip: rust cli
Browse files Browse the repository at this point in the history
  • Loading branch information
burgerdev committed Oct 11, 2024
1 parent aac8adf commit 3fda007
Show file tree
Hide file tree
Showing 3 changed files with 293 additions and 0 deletions.
200 changes: 200 additions & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,29 @@ 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"

[lib]
name = "glome"
path = "src/lib.rs"

[[bin]]
name = "glome"
path = "src/cli/bin.rs"

required-features = ["cli"]
81 changes: 81 additions & 0 deletions rust/src/cli/bin.rs
Original file line number Diff line number Diff line change
@@ -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<u8>,
}

#[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),
}
}

0 comments on commit 3fda007

Please sign in to comment.