/// Decrypts asymmetrically-encrypted OpenPGP messages using the /// openpgp crate, Sequoia's low-level API. use std::collections::HashMap; use std::env; use std::io; extern crate failure; extern crate openpgp; use openpgp::parse::stream::{ Decryptor, DecryptionHelper, Secret, VerificationHelper, VerificationResult, }; pub fn main() { let args: Vec = env::args().collect(); if args.len() < 2 { panic!("A simple decryption filter.\n\n\ Usage: {} [...] output\n", args[0]); } // Read the transferable secret keys from the given files. let tpks = args[1..].iter().map(|f| { openpgp::TPK::from_reader( // Use an openpgp::Reader so that we accept both armored // and plain PGP data. openpgp::Reader::from_file(f) .expect("Failed to open file")) .expect("Failed to read key") }).collect(); // First, use an openpgp::Reader so that we accept both armored // and plain PGP data. let reader = openpgp::Reader::from_reader(io::stdin()) .expect("Failed to open file"); // Now, create a decryptor with a helper using the given TPKs. let mut decryptor = Decryptor::from_reader(reader, Helper::new(tpks)).unwrap(); // Finally, stream the decrypted data to stdout. io::copy(&mut decryptor, &mut io::stdout()) .expect("Decryption failed"); } /// This helper provides secrets for the decryption, fetches public /// keys for the signature verification and implements the /// verification policy. struct Helper { keys: HashMap, i: usize, } impl Helper { /// Creates a Helper for the given TPKs with appropriate secrets. fn new(tpks: Vec) -> Self { // Map (sub)KeyIDs to secrets. let mut keys = HashMap::new(); for tpk in tpks { for (sig, key) in tpk.keys() { if sig.map(|s| (s.key_flags().can_encrypt_at_rest() || s.key_flags().can_encrypt_for_transport())) .unwrap_or(false) { // Only handle unencrypted secret keys. if let Some(openpgp::SecretKey::Unencrypted { ref mpis }) = key.secret() { keys.insert(key.fingerprint().to_keyid(), Secret::Asymmetric { identity: tpk.fingerprint(), key: key.clone(), secret: mpis.clone(), }); } } } } Helper { keys: keys, i: 0, } } } impl DecryptionHelper for Helper { fn get_secret(&mut self, pkesks: &[&openpgp::packet::PKESK], _: &[&openpgp::packet::SKESK]) -> failure::Fallible> { let r = pkesks .iter() .nth(self.i) .and_then(|pkesk| { self.keys.get(pkesk.recipient()) .map(|s| (*s).clone()) }); self.i += 1; Ok(r) } } impl VerificationHelper for Helper { fn get_public_keys(&mut self, _ids: &[openpgp::KeyID]) -> failure::Fallible> { Ok(Vec::new()) // Feed the TPKs to the verifier here. } fn check(&mut self, _sigs: Vec>) -> failure::Fallible<()> { Ok(()) // Implement your verification policy here. } }