keyfork/keyfork-shard/src/bin/keyfork-shard-combine-openp...

99 lines
2.4 KiB
Rust
Raw Normal View History

2023-10-18 09:28:12 +00:00
use std::{
collections::VecDeque,
env,
io::{stdin, stdout},
path::PathBuf,
process::ExitCode,
str::FromStr,
};
use keyfork_shard::{combine, discover_certs, openpgp::Cert, EncryptedMessage};
use openpgp::{
packet::Packet,
parse::Parse,
PacketPile,
};
use sequoia_openpgp as openpgp;
#[derive(Clone, Debug)]
enum Error {
Usage(String),
}
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 key_discovery")
}
}
}
}
impl std::error::Error for Error {}
type Result<T, E = Box<dyn std::error::Error>> = std::result::Result<T, E>;
fn validate(threshold: &str, key_discovery: &str) -> Result<(u8, Vec<Cert>)> {
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)?;
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, key_discovery] => validate(threshold, key_discovery)?,
_ => return Err(Error::Usage(program_name).into()),
};
let stdin = stdin();
let mut pkesks = Vec::new();
let mut encrypted_messages = VecDeque::new();
for packet in PacketPile::from_reader(stdin)?.into_children() {
match packet {
Packet::PKESK(p) => pkesks.push(p),
Packet::SEIP(s) => {
encrypted_messages.push_back(EncryptedMessage::with_swap(&mut pkesks, s));
}
s => {
panic!("Invalid variant found: {}", s.tag());
}
}
}
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
}