summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2018-07-05 11:42:11 +0200
committerJustus Winter <justus@sequoia-pgp.org>2018-07-05 11:42:11 +0200
commit92904ac94e4309103d0661e472cad3a9f78c558c (patch)
tree15aa0b37ce927d8788640ba3f4f126c9cc687f6b
parentcc26880a47492fc5596ceacc30b31d962a8530d2 (diff)
openpgp: Add simple decryption example.
-rw-r--r--openpgp/examples/decrypt-with.rs121
1 files changed, 121 insertions, 0 deletions
diff --git a/openpgp/examples/decrypt-with.rs b/openpgp/examples/decrypt-with.rs
new file mode 100644
index 00000000..3ffaa0a3
--- /dev/null
+++ b/openpgp/examples/decrypt-with.rs
@@ -0,0 +1,121 @@
+/// This program demonstrates how to decrypt a stream of data.
+
+use std::env;
+use std::io;
+use std::collections::HashMap;
+
+extern crate openpgp;
+use openpgp::{
+ Packet,
+ KeyID,
+ Key,
+ TPK,
+ SecretKey,
+};
+use openpgp::parse::PacketParserResult;
+
+pub fn main() {
+ let args: Vec<String> = env::args().collect();
+ if args.len() < 2 {
+ panic!("A simple decryption filter.\n\n\
+ Usage: {} <keyfile> [<keyfile>...] <input >output\n", args[0]);
+ }
+
+ // Read the transferable secret keys from the given files.
+ let mut keys: HashMap<KeyID, Key> = HashMap::new();
+ for f in args[1..].iter() {
+ let tsk = 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");
+ for key in tsk.keys() {
+ // XXX this is cheating, we just add all keys, even if
+ // they should not be used for encryption
+ keys.insert(key.fingerprint().to_keyid(), key.clone());
+ }
+ }
+
+ #[derive(PartialEq)]
+ enum State {
+ Start(Vec<openpgp::PKESK>, Vec<openpgp::SKESK>),
+ Deciphered,
+ Done,
+ }
+ let mut state = State::Start(vec![], vec![]);
+ let mut input = io::stdin();
+ let mut ppr
+ = openpgp::parse::PacketParser::from_reader(
+ openpgp::Reader::from_reader(&mut input)
+ .expect("Failed to build reader"))
+ .expect("Failed to build parser");
+
+ while let PacketParserResult::Some(mut pp) = ppr {
+ state = match state {
+ // Look for an PKESK or SKESK packet.
+ State::Start(mut pkesks, mut skesks) =>
+ match pp.packet {
+ Packet::SEIP(_) => {
+ let mut state = None;
+ for pkesk in pkesks.iter() {
+ if let Some(tsk) = keys.get(&pkesk.recipient) {
+ if let Some(SecretKey::Unencrypted{ref mpis}) = tsk.secret {
+ if let Ok((algo, key)) = pkesk.decrypt(tsk, mpis) {
+ let r = pp.decrypt(algo, &key[..]);
+ if r.is_ok() {
+ state = Some(State::Deciphered);
+ break;
+ }
+ }
+ }
+ }
+ }
+ state.unwrap_or(State::Start(pkesks, skesks))
+ },
+ _ => State::Start(pkesks, skesks),
+ },
+
+ // Look for the literal data packet.
+ State::Deciphered =>
+ if let Packet::Literal(_) = pp.packet {
+ io::copy(&mut pp, &mut io::stdout())
+ .expect("Failed to copy data");
+ State::Done
+ } else {
+ State::Deciphered
+ },
+
+ // We continue to parse, useful for dumping
+ // encrypted packets.
+ State::Done => State::Done,
+ };
+
+ let (packet, _, ppr_tmp, _) = pp.recurse()
+ .expect("Failed to recurse");
+ ppr = ppr_tmp;
+
+ state = match state {
+ // Look for an PKESK or SKESK packet.
+ State::Start(mut pkesks, mut skesks) =>
+ match packet {
+ Packet::PKESK(pkesk) => {
+ pkesks.push(pkesk);
+ State::Start(pkesks, skesks)
+ },
+ Packet::SKESK(skesk) => {
+ skesks.push(skesk);
+ State::Start(pkesks, skesks)
+ },
+ _ => State::Start(pkesks, skesks),
+ },
+
+ // Do nothing in all other states.
+ s => s,
+ };
+ }
+
+ if state != State::Done {
+ panic!("decryption failed");
+ }
+}