summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNora Widdecke <nora@sequoia-pgp.org>2022-06-29 19:11:00 +0200
committerNora Widdecke <nora@sequoia-pgp.org>2022-06-29 19:19:28 +0200
commitfbfb792c0a6d41397daf5475d25db7785f689b03 (patch)
treede02aa4fbf0ef82e2f30625e10f354fb0f84537d
parent56ad63f1b12f41ec38eddf2a2e8131a66a2e22fa (diff)
sq: Add packet decrypt --session-key.
- Allow giving multiple session keys, try them all until one decrypts the packet.
-rw-r--r--sq/src/commands/decrypt.rs6
-rw-r--r--sq/src/sq-usage.rs3
-rw-r--r--sq/src/sq.rs2
-rw-r--r--sq/src/sq_cli.rs6
-rw-r--r--sq/tests/sq-packet-decrypt.rs75
5 files changed, 90 insertions, 2 deletions
diff --git a/sq/src/commands/decrypt.rs b/sq/src/commands/decrypt.rs
index 312b4a40..8e362621 100644
--- a/sq/src/commands/decrypt.rs
+++ b/sq/src/commands/decrypt.rs
@@ -393,11 +393,13 @@ pub fn decrypt(config: Config,
pub fn decrypt_unwrap(config: Config,
input: &mut (dyn io::Read + Sync + Send),
output: &mut dyn io::Write,
- secrets: Vec<Cert>, dump_session_key: bool)
+ secrets: Vec<Cert>,
+ session_keys: Vec<CliSessionKey>,
+ dump_session_key: bool)
-> Result<()>
{
let mut helper = Helper::new(&config, None, 0, Vec::new(), secrets,
- Vec::new(),
+ session_keys,
dump_session_key, false);
let mut ppr = PacketParser::from_reader(input)?;
diff --git a/sq/src/sq-usage.rs b/sq/src/sq-usage.rs
index 7b2bc0df..05f2c7fa 100644
--- a/sq/src/sq-usage.rs
+++ b/sq/src/sq-usage.rs
@@ -1557,6 +1557,9 @@
//! --recipient-key <KEY>
//! Decrypts the message with KEY
//!
+//! --session-key <SESSION-KEY>
+//! Decrypts an encrypted message using SESSION-KEY
+//!
//! EXAMPLES:
//!
//! # Unwraps the encryption revealing the signed message
diff --git a/sq/src/sq.rs b/sq/src/sq.rs
index 108a47f6..1ad1f500 100644
--- a/sq/src/sq.rs
+++ b/sq/src/sq.rs
@@ -695,10 +695,12 @@ fn main() -> Result<()> {
let secrets =
load_keys(command.secret_key_file.iter().map(|s| s.as_ref()))?;
+ let session_keys = command.session_key;
commands::decrypt::decrypt_unwrap(
config,
&mut input, &mut output,
secrets,
+ session_keys,
command.dump_session_key)?;
output.finalize()?;
},
diff --git a/sq/src/sq_cli.rs b/sq/src/sq_cli.rs
index 9d6dfb86..076ce430 100644
--- a/sq/src/sq_cli.rs
+++ b/sq/src/sq_cli.rs
@@ -519,6 +519,12 @@ pub struct PacketDecryptCommand {
)]
pub private_key_store: Option<String>,
#[clap(
+ long = "session-key",
+ value_name = "SESSION-KEY",
+ help = "Decrypts an encrypted message using SESSION-KEY",
+ )]
+ pub session_key: Vec<CliSessionKey>,
+ #[clap(
long = "dump-session-key",
help = "Prints the session key to stderr",
)]
diff --git a/sq/tests/sq-packet-decrypt.rs b/sq/tests/sq-packet-decrypt.rs
new file mode 100644
index 00000000..5a466ac7
--- /dev/null
+++ b/sq/tests/sq-packet-decrypt.rs
@@ -0,0 +1,75 @@
+#[cfg(test)]
+mod sq_packet_decrypt {
+ use assert_cmd::Command;
+ use predicates::prelude::*;
+
+ use openpgp::Result;
+ use sequoia_openpgp as openpgp;
+
+ fn artifact(filename: &str) -> String {
+ format!("tests/data/{}", filename)
+ }
+
+ // Integration tests should be done with subplot.
+ // However, at this time, subplot does not support static binary files in tests.
+ // Generating the test files would mean encrypting some static text symmetrically
+ // and then extracting the session key, which means parsing of human readabe cli output.
+ // So, for now, the tests go here.
+ #[test]
+ fn session_key() -> Result<()> {
+ Command::cargo_bin("sq")
+ .unwrap()
+ .arg("packet")
+ .arg("decrypt")
+ .args(["--session-key", "1FE820EC21FB5D7E33D83367106D1D3747DCD48E6320C1AEC57EE7D18FC437D4"])
+ .arg(artifact("messages/rsa.msg.pgp"))
+ .assert()
+ .success()
+ .stderr(predicate::str::contains("Encrypted with Session Key"));
+ Ok(())
+ }
+
+ #[test]
+ fn session_key_with_prefix() -> Result<()> {
+ Command::cargo_bin("sq")
+ .unwrap()
+ .arg("packet")
+ .arg("decrypt")
+ .args(["--session-key", "9:1FE820EC21FB5D7E33D83367106D1D3747DCD48E6320C1AEC57EE7D18FC437D4"])
+ .arg(artifact("messages/rsa.msg.pgp"))
+ .assert()
+ .success()
+ .stderr(predicate::str::contains("Decryption failed").not());
+ Ok(())
+ }
+
+ #[test]
+ fn session_key_multiple() -> Result<()> {
+ Command::cargo_bin("sq")
+ .unwrap()
+ .arg("packet")
+ .arg("decrypt")
+ .args(["--session-key", "2FE820EC21FB5D7E33D83367106D1D3747DCD48E6320C1AEC57EE7D18FC437D4"])
+ .args(["--session-key", "9:1FE820EC21FB5D7E33D83367106D1D3747DCD48E6320C1AEC57EE7D18FC437D4"])
+ .args(["--session-key", "3FE820EC21FB5D7E33D83367106D1D3747DCD48E6320C1AEC57EE7D18FC437D4"])
+ .arg(artifact("messages/rsa.msg.pgp"))
+ .assert()
+ .success()
+ .stderr(predicate::str::contains("Decryption failed").not());
+ Ok(())
+ }
+
+ #[test]
+ fn session_key_wrong_key() -> Result<()> {
+ Command::cargo_bin("sq")
+ .unwrap()
+ .arg("packet")
+ .arg("decrypt")
+ .args(["--session-key", "BB9CCB8EDE22DC222C83BD1C63AEB97335DDC7B696DB171BD16EAA5784CC0478"])
+ .arg(artifact("messages/rsa.msg.pgp"))
+ .assert()
+ .failure()
+ .stderr(predicate::str::contains("No key to decrypt message"));
+ Ok(())
+ }
+}