//! Split a hex-encoded secret into OpenPGP shards use std::{env, path::PathBuf, process::ExitCode, str::FromStr}; use keyfork_shard::{Format, openpgp::OpenPGP}; #[derive(Clone, Debug)] enum Error { Usage(String), Input, } impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Error::Usage(program_name) => { write!(f, "Usage: {program_name} threshold max key_discovery") } Error::Input => f.write_str("Expected hex encoded input"), } } } impl std::error::Error for Error {} type Result> = std::result::Result; fn validate(threshold: &str, max: &str, key_discovery: &str) -> Result<(u8, u8, PathBuf)> { let threshold = u8::from_str(threshold)?; let max = u8::from_str(max)?; let key_discovery = PathBuf::from(key_discovery); std::fs::metadata(&key_discovery)?; Ok((threshold, max, key_discovery)) } fn run() -> Result<()> { let mut args = env::args(); let program_name = args.next().expect("program name"); let args = args.collect::>(); let (threshold, max, key_discovery) = match args.as_slice() { [threshold, max, key_discovery] => validate(threshold, max, key_discovery)?, _ => return Err(Error::Usage(program_name).into()), }; let input = { use std::io::stdin; let Some(line) = stdin().lines().next() else { return Err(Error::Input.into()); }; smex::decode(line?)? }; let openpgp = OpenPGP; openpgp.shard_and_encrypt(threshold, max, &input, key_discovery.as_path(), std::io::stdout())?; Ok(()) } fn main() -> ExitCode { let result = run(); if let Err(e) = result { eprintln!("Error: {e}"); return ExitCode::FAILURE; } ExitCode::SUCCESS }