79 lines
2.0 KiB
Rust
79 lines
2.0 KiB
Rust
use std::{
|
|
env,
|
|
fs::File,
|
|
io::{stdin, stdout},
|
|
path::PathBuf,
|
|
process::ExitCode,
|
|
str::FromStr,
|
|
};
|
|
|
|
use keyfork_shard::openpgp::{combine, discover_certs, openpgp::Cert, parse_messages};
|
|
|
|
type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
|
|
|
|
fn validate(
|
|
threshold: &str,
|
|
key_discovery: &str,
|
|
recovery_file: &str,
|
|
) -> Result<(u8, Vec<Cert>, PathBuf)> {
|
|
let threshold = u8::from_str(threshold)?;
|
|
let key_discovery = PathBuf::from(key_discovery);
|
|
|
|
// Verify path exists
|
|
std::fs::metadata(&key_discovery)?;
|
|
|
|
// Load certs from path
|
|
let certs = discover_certs(key_discovery)?;
|
|
|
|
let recovery_file = PathBuf::from(if recovery_file == "=" {
|
|
eprintln!("loading certs from stdin; note that prompting smartcard devices will not work");
|
|
"/dev/stdin"
|
|
} else {
|
|
recovery_file
|
|
});
|
|
|
|
std::fs::metadata(&recovery_file)?;
|
|
|
|
Ok((threshold, certs, recovery_file))
|
|
}
|
|
|
|
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, recovery_file) = match args.as_slice() {
|
|
[threshold, key_discovery, recovery_file] => {
|
|
validate(threshold, key_discovery, recovery_file)?
|
|
}
|
|
[threshold, key_discovery] => {
|
|
validate(threshold, key_discovery, "-")?
|
|
}
|
|
_ => panic!("Usage: {program_name} threshold key_discovery recovery_file"),
|
|
};
|
|
|
|
let mut encrypted_messages = parse_messages(File::open(recovery_file)?)?;
|
|
|
|
let encrypted_metadata = encrypted_messages
|
|
.pop_front()
|
|
.expect("any pgp encrypted message");
|
|
|
|
combine(
|
|
threshold,
|
|
cert_list,
|
|
encrypted_metadata,
|
|
encrypted_messages.into(),
|
|
stdout(),
|
|
)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn main() -> ExitCode {
|
|
let result = run();
|
|
if let Err(e) = result {
|
|
eprintln!("Error: {e}");
|
|
return ExitCode::FAILURE;
|
|
}
|
|
ExitCode::SUCCESS
|
|
}
|