summaryrefslogtreecommitdiffstats
path: root/tool
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-09-06 13:47:50 +0200
committerJustus Winter <justus@sequoia-pgp.org>2019-09-06 16:42:12 +0200
commit38a4d2b4ff4fc4512b31a4ff4e4ddd8a6b3c7503 (patch)
tree469d667b6bab8333df02c7a2402b9edabbe08419 /tool
parent4d642187f1df0c9a4c60dc2355c797ebac6fcd4f (diff)
openpgp: Rework streaming encryptor.
- Instead of giving a set of TPKs to the encryptor, hand in a set of recipients, which are (keyid, key)-tuples, conveniently created from key queries over TPKs. This simplifies the encryptor, and makes the key selection explicit. - Drop the EncryptionMode type. - As a nice side effect, we can now generate encrypted messages with wildcard recipient addresses.
Diffstat (limited to 'tool')
-rw-r--r--tool/src/commands/mod.rs23
-rw-r--r--tool/src/sq-usage.rs4
-rw-r--r--tool/src/sq.rs12
-rw-r--r--tool/src/sq_cli.rs10
4 files changed, 45 insertions, 4 deletions
diff --git a/tool/src/commands/mod.rs b/tool/src/commands/mod.rs
index 0db911ce..2fc31b6a 100644
--- a/tool/src/commands/mod.rs
+++ b/tool/src/commands/mod.rs
@@ -24,7 +24,7 @@ use crate::openpgp::parse::stream::{
MessageStructure, MessageLayer,
};
use crate::openpgp::serialize::stream::{
- Message, Signer, LiteralWriter, Encryptor, EncryptionMode,
+ Message, Signer, LiteralWriter, Encryptor, Recipient,
Compressor,
};
use crate::openpgp::serialize::padding::{
@@ -89,6 +89,7 @@ pub fn encrypt(store: &mut store::Store,
input: &mut io::Read, output: &mut io::Write,
npasswords: usize, recipients: Vec<&str>,
mut tpks: Vec<openpgp::TPK>, signers: Vec<openpgp::TPK>,
+ mode: KeyFlags,
compression: &str)
-> Result<()> {
for r in recipients {
@@ -107,8 +108,23 @@ pub fn encrypt(store: &mut store::Store,
let mut signers = get_signing_keys(&signers)?;
- // Build a vector of references to hand to Encryptor.
+ // Build a vector of references to hand to Signer.
let recipients: Vec<&openpgp::TPK> = tpks.iter().collect();
+
+ // Build a vector of recipients to hand to Encryptor.
+ let mut recipient_subkeys: Vec<Recipient> = Vec::new();
+ for tpk in tpks.iter() {
+ let mut count = 0;
+ for (_, _, key) in tpk.keys_valid().key_flags(mode.clone()) {
+ recipient_subkeys.push(key.into());
+ count += 1;
+ }
+ if count == 0 {
+ return Err(failure::format_err!(
+ "Key {} has no suitable encryption key", tpk));
+ }
+ }
+
let passwords_: Vec<&openpgp::crypto::Password> =
passwords.iter().collect();
@@ -118,8 +134,7 @@ pub fn encrypt(store: &mut store::Store,
// We want to encrypt a literal data packet.
let mut sink = Encryptor::new(message,
&passwords_,
- &recipients,
- EncryptionMode::AtRest,
+ recipient_subkeys,
None, None)
.context("Failed to create encryptor")?;
diff --git a/tool/src/sq-usage.rs b/tool/src/sq-usage.rs
index c5580112..e06ea6b5 100644
--- a/tool/src/sq-usage.rs
+++ b/tool/src/sq-usage.rs
@@ -78,6 +78,10 @@
//! OPTIONS:
//! --compression <KIND> Selects compression scheme to use [default: pad] [possible values: none,
//! pad, zip, zlib, bzip2]
+//! --mode <MODE> Selects what kind of keys are considered for encryption. Transport select
+//! subkeys marked as suitable for transport encryption, rest selects those
+//! for encrypting data at rest, and all selects all encryption-capable
+//! subkeys [default: all] [possible values: transport, rest, all]
//! -o, --output <FILE> Sets the output file to use
//! -r, --recipient <LABEL>... Recipient to encrypt for (can be given multiple times)
//! --recipient-key-file <TPK-FILE>... Recipient to encrypt for, given as a file (can be given multiple times)
diff --git a/tool/src/sq.rs b/tool/src/sq.rs
index 9962a0a4..bd1d1129 100644
--- a/tool/src/sq.rs
+++ b/tool/src/sq.rs
@@ -26,6 +26,7 @@ extern crate sequoia_store;
use crate::openpgp::{armor, autocrypt, Fingerprint, TPK};
use crate::openpgp::conversions::hex;
+use crate::openpgp::packet::KeyFlags;
use crate::openpgp::parse::Parse;
use crate::openpgp::serialize::Serialize;
use sequoia_core::{Context, NetworkPolicy};
@@ -206,9 +207,20 @@ fn real_main() -> Result<(), failure::Error> {
let additional_secrets = m.values_of("signer-key-file")
.map(load_tpks)
.unwrap_or(Ok(vec![]))?;
+ let mode = match m.value_of("mode").expect("has default") {
+ "rest" => KeyFlags::default()
+ .set_encrypt_at_rest(true),
+ "transport" => KeyFlags::default()
+ .set_encrypt_for_transport(true),
+ "all" => KeyFlags::default()
+ .set_encrypt_at_rest(true)
+ .set_encrypt_for_transport(true),
+ _ => unreachable!("uses possible_values"),
+ };
commands::encrypt(&mut store, &mut input, &mut output,
m.occurrences_of("symmetric") as usize,
recipients, additional_tpks, additional_secrets,
+ mode,
m.value_of("compression").expect("has default"))?;
},
("sign", Some(m)) => {
diff --git a/tool/src/sq_cli.rs b/tool/src/sq_cli.rs
index feb9d755..9ec8ca8e 100644
--- a/tool/src/sq_cli.rs
+++ b/tool/src/sq_cli.rs
@@ -112,6 +112,16 @@ pub fn build() -> App<'static, 'static> {
.multiple(true)
.help("Encrypt with a password \
(can be given multiple times)"))
+ .arg(Arg::with_name("mode").value_name("MODE")
+ .long("mode")
+ .possible_values(&["transport", "rest", "all"])
+ .default_value("all")
+ .help("Selects what kind of keys are considered for \
+ encryption. Transport select subkeys marked \
+ as suitable for transport encryption, rest \
+ selects those for encrypting data at rest, \
+ and all selects all encryption-capable \
+ subkeys"))
.arg(Arg::with_name("compression")
.value_name("KIND")
.long("compression")