keyfork/crates/keyfork-shard/src/bin/keyfork-shard-split-openpgp.rs

88 lines
2.4 KiB
Rust

//!
use std::{env, path::PathBuf, process::ExitCode, str::FromStr};
use keyfork_shard::openpgp::{discover_certs, openpgp::Cert, split};
#[derive(Clone, Debug)]
enum Error {
Usage(String),
Input,
Threshold(u8, u8),
InvalidCertCount(usize, u8),
}
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"),
Error::Threshold(threshold, max) => {
write!(
f,
"Invalid threshold: 0 < threshold {threshold} <= max {max} < 256"
)
}
Error::InvalidCertCount(count, max) => {
write!(f, "Invalid cert count: count {count} != max {max}")
}
}
}
}
impl std::error::Error for Error {}
type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
fn validate(threshold: &str, max: &str, key_discovery: &str) -> Result<(u8, Vec<Cert>)> {
let threshold = u8::from_str(threshold)?;
let max = u8::from_str(max)?;
let key_discovery = PathBuf::from(key_discovery);
if threshold > max {
return Err(Error::Threshold(threshold, max).into());
}
// Verify path exists
std::fs::metadata(&key_discovery)?;
// Load certs from path
let certs = discover_certs(key_discovery)?;
if certs.len() != max.into() {
return Err(Error::InvalidCertCount(certs.len(), max).into());
}
Ok((threshold, certs))
}
fn run() -> Result<()> {
let mut args = env::args();
let program_name = args.next().expect("program name");
let args = args.collect::<Vec<_>>();
let (threshold, cert_list) = 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?)?
};
split(threshold, cert_list, &input, std::io::stdout())?;
Ok(())
}
fn main() -> ExitCode {
let result = run();
if let Err(e) = result {
eprintln!("Error: {e}");
return ExitCode::FAILURE;
}
ExitCode::SUCCESS
}