diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2018-04-12 17:49:00 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2018-05-03 17:31:40 +0200 |
commit | fb73ab393c1235d57e6e72514e89f50b24fd14ee (patch) | |
tree | d6291d2479413eed8281200f48e3a29f193310f7 /tool | |
parent | c4ee712d84e03164cd77d6e63c7a0cae4496cab8 (diff) |
tool: Move the decryption command to a new file.
Diffstat (limited to 'tool')
-rw-r--r-- | tool/src/commands.rs | 88 | ||||
-rw-r--r-- | tool/src/main.rs | 83 |
2 files changed, 91 insertions, 80 deletions
diff --git a/tool/src/commands.rs b/tool/src/commands.rs new file mode 100644 index 00000000..2f3f3422 --- /dev/null +++ b/tool/src/commands.rs @@ -0,0 +1,88 @@ +use failure; +use std::io; +use rpassword; + +extern crate openpgp; +use openpgp::{Packet, Tag}; + +// Indent packets according to their recursion level. +const INDENT: &'static str + = " "; + +pub fn decrypt(input: &mut io::Read, output: &mut io::Write, dump: bool) + -> Result<(), failure::Error> { + #[derive(PartialEq)] + enum State { + Start, + Decrypted(u8, Vec<u8>), + Deciphered, + Done, + } + let mut state = State::Start; + let mut ppo = openpgp::parse::PacketParser::from_reader(input)?; + + while let Some(mut pp) = ppo { + state = match state { + // Look for an PKESK or SKESK packet. + State::Start => + match pp.packet { + Packet::Unknown(ref u) => { + match u.tag { + Tag::PKESK => + eprintln!("Decryption using PKESK not yet \ + supported."), + _ => (), + } + State::Start + }, + Packet::SKESK(ref skesk) => { + let pass = rpassword::prompt_password_stderr( + "Enter passphrase to decrypt message: ")?; + match skesk.decrypt(pass.into_bytes().as_ref()) { + Ok((algo, key)) => State::Decrypted(algo.into(), key), + Err(e) => { + eprintln!("Decryption failed: {}", e); + State::Start + }, + } + }, + _ => State::Start, + }, + + // Look for an SEIP packet. + State::Decrypted(algo, key) => + if let Packet::SEIP(_) = pp.packet { + pp.decrypt(algo.into(), &key[..])?; + State::Deciphered + } else { + State::Decrypted(algo, key) + }, + + // Look for the literal data packet. + State::Deciphered => + if let Packet::Literal(_) = pp.packet { + io::copy(&mut pp, output)?; + State::Done + } else { + State::Deciphered + }, + + // We continue to parse, useful for dumping + // encrypted packets. + State::Done => State::Done, + }; + + if dump { + eprintln!("{}{:?}", + &INDENT[0..pp.recursion_depth as usize], pp.packet); + } + + let (_, _, ppo_tmp, _) = pp.recurse()?; + ppo = ppo_tmp; + } + + if state != State::Done { + return Err(failure::err_msg("Decryption failed.")); + } + Ok(()) +} diff --git a/tool/src/main.rs b/tool/src/main.rs index 6c7f725e..670e2398 100644 --- a/tool/src/main.rs +++ b/tool/src/main.rs @@ -20,12 +20,13 @@ extern crate sequoia_core; extern crate sequoia_net; extern crate sequoia_store; -use openpgp::{armor, Fingerprint, TPK, Packet, Tag}; +use openpgp::{armor, Fingerprint, TPK}; use sequoia_core::{Context, NetworkPolicy}; use sequoia_net::KeyServer; use sequoia_store::{Store, LogIter}; mod cli; +mod commands; fn open_or_stdin(f: Option<&str>) -> Result<Box<io::Read>, failure::Error> { match f { @@ -45,84 +46,6 @@ fn create_or_stdout(f: Option<&str>) -> Result<Box<io::Write>, failure::Error> { const INDENT: &'static str = " "; -fn decrypt(input: &mut io::Read, output: &mut io::Write, dump: bool) - -> Result<(), failure::Error> { - #[derive(PartialEq)] - enum State { - Start, - Decrypted(u8, Vec<u8>), - Deciphered, - Done, - } - let mut state = State::Start; - let mut ppo = openpgp::parse::PacketParser::from_reader(input)?; - - while let Some(mut pp) = ppo { - state = match state { - // Look for an PKESK or SKESK packet. - State::Start => - match pp.packet { - Packet::Unknown(ref u) => { - match u.tag { - Tag::PKESK => - eprintln!("Decryption using PKESK not yet \ - supported."), - _ => (), - } - State::Start - }, - Packet::SKESK(ref skesk) => { - let pass = rpassword::prompt_password_stderr( - "Enter passphrase to decrypt message: ")?; - match skesk.decrypt(pass.into_bytes().as_ref()) { - Ok((algo, key)) => State::Decrypted(algo.into(), key), - Err(e) => { - eprintln!("Decryption failed: {}", e); - State::Start - }, - } - }, - _ => State::Start, - }, - - // Look for an SEIP packet. - State::Decrypted(algo, key) => - if let Packet::SEIP(_) = pp.packet { - pp.decrypt(algo.into(), &key[..])?; - State::Deciphered - } else { - State::Decrypted(algo, key) - }, - - // Look for the literal data packet. - State::Deciphered => - if let Packet::Literal(_) = pp.packet { - io::copy(&mut pp, output)?; - State::Done - } else { - State::Deciphered - }, - - // We continue to parse, useful for dumping - // encrypted packets. - State::Done => State::Done, - }; - - if dump { - eprintln!("{}{:?}", - &INDENT[0..pp.recursion_depth as usize], pp.packet); - } - - let (_, _, ppo_tmp, _) = pp.recurse()?; - ppo = ppo_tmp; - } - - if state != State::Done { - return Err(failure::err_msg("Decryption failed.")); - } - Ok(()) -} - fn real_main() -> Result<(), failure::Error> { let matches = cli::build().get_matches(); @@ -150,7 +73,7 @@ fn real_main() -> Result<(), failure::Error> { } else { input }; - return decrypt(&mut input, &mut output, dump); + commands::decrypt(&mut input, &mut output, dump)?; }, ("enarmor", Some(m)) => { let mut input = open_or_stdin(m.value_of("input"))?; |