diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2019-09-06 13:47:50 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2019-09-06 16:42:12 +0200 |
commit | 38a4d2b4ff4fc4512b31a4ff4e4ddd8a6b3c7503 (patch) | |
tree | 469d667b6bab8333df02c7a2402b9edabbe08419 /tool/src | |
parent | 4d642187f1df0c9a4c60dc2355c797ebac6fcd4f (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/src')
-rw-r--r-- | tool/src/commands/mod.rs | 23 | ||||
-rw-r--r-- | tool/src/sq-usage.rs | 4 | ||||
-rw-r--r-- | tool/src/sq.rs | 12 | ||||
-rw-r--r-- | tool/src/sq_cli.rs | 10 |
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") |