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

67 lines
1.9 KiB
Rust

//! 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<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
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::<Vec<_>>();
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
}