99 lines
2.4 KiB
Rust
99 lines
2.4 KiB
Rust
|
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
|
||
|
}
|