summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2020-12-11 15:16:45 +0100
committerJustus Winter <justus@sequoia-pgp.org>2020-12-11 15:19:48 +0100
commite5712889a0f6f678323ed86c6aad54b807694a7c (patch)
tree47cf23000fc1b544b419a6b796068a34549c0eb7
parentef6a1c9af05a97d962933242545c7266c01d2973 (diff)
sq: Add switch to fall back to an expired encryption subkey.
-rw-r--r--sq/src/commands/mod.rs34
-rw-r--r--sq/src/sq-usage.rs10
-rw-r--r--sq/src/sq.rs4
-rw-r--r--sq/src/sq_cli.rs5
4 files changed, 45 insertions, 8 deletions
diff --git a/sq/src/commands/mod.rs b/sq/src/commands/mod.rs
index 83a02237..06110976 100644
--- a/sq/src/commands/mod.rs
+++ b/sq/src/commands/mod.rs
@@ -81,7 +81,9 @@ pub fn encrypt<'a>(policy: &'a dyn Policy,
npasswords: usize, recipients: &'a [openpgp::Cert],
signers: Vec<openpgp::Cert>,
mode: openpgp::types::KeyFlags, compression: &str,
- time: Option<SystemTime>)
+ time: Option<SystemTime>,
+ use_expired_subkey: bool,
+)
-> Result<()> {
let mut passwords: Vec<crypto::Password> = Vec::with_capacity(npasswords);
for n in 0..npasswords {
@@ -112,8 +114,34 @@ pub fn encrypt<'a>(policy: &'a dyn Policy,
count += 1;
}
if count == 0 {
- return Err(anyhow::anyhow!(
- "Key {} has no suitable encryption key", cert));
+ let mut expired_keys = Vec::new();
+ for ka in cert.keys().with_policy(policy, None).revoked(false)
+ .key_flags(&mode).supported()
+ {
+ let key = ka.key();
+ expired_keys.push(
+ (ka.binding_signature().key_expiration_time(key)
+ .expect("Key must have an expiration time"),
+ key));
+ }
+ expired_keys.sort_by_key(|(expiration_time, _)| *expiration_time);
+
+ if let Some((expiration_time, key)) = expired_keys.last() {
+ if use_expired_subkey {
+ recipient_subkeys.push((*key).into());
+ } else {
+ use chrono::{DateTime, offset::Utc};
+ return Err(anyhow::anyhow!(
+ "The last suitable encryption key of cert {} expired \
+ on {}\n\
+ Hint: Use --use-expired-subkey to use it anyway.",
+ cert,
+ DateTime::<Utc>::from(*expiration_time)));
+ }
+ } else {
+ return Err(anyhow::anyhow!(
+ "Cert {} has no suitable encryption key", cert));
+ }
}
}
diff --git a/sq/src/sq-usage.rs b/sq/src/sq-usage.rs
index 2729cafa..28e3085a 100644
--- a/sq/src/sq-usage.rs
+++ b/sq/src/sq-usage.rs
@@ -74,10 +74,12 @@
//! sq encrypt [FLAGS] [OPTIONS] [--] [FILE]
//!
//! FLAGS:
-//! -B, --binary Don't ASCII-armor encode the OpenPGP data
-//! -h, --help Prints help information
-//! -s, --symmetric Encrypt with a password (can be given multiple times)
-//! -V, --version Prints version information
+//! -B, --binary Don't ASCII-armor encode the OpenPGP data
+//! -h, --help Prints help information
+//! -s, --symmetric Encrypt with a password (can be given multiple times)
+//! --use-expired-subkey If a certificate has only expired encryption-capable subkeys, fall back to using the one
+//! that expired last
+//! -V, --version Prints version information
//!
//! OPTIONS:
//! --compression <KIND>
diff --git a/sq/src/sq.rs b/sq/src/sq.rs
index 970e2ebe..f93c0370 100644
--- a/sq/src/sq.rs
+++ b/sq/src/sq.rs
@@ -279,7 +279,9 @@ fn main() -> Result<()> {
&recipients, additional_secrets,
mode,
m.value_of("compression").expect("has default"),
- time.into())?;
+ time.into(),
+ m.is_present("use-expired-subkey"),
+ )?;
},
("sign", Some(m)) => {
let mut input = open_or_stdin(m.value_of("input"))?;
diff --git a/sq/src/sq_cli.rs b/sq/src/sq_cli.rs
index 464d78b4..76164989 100644
--- a/sq/src/sq_cli.rs
+++ b/sq/src/sq_cli.rs
@@ -145,6 +145,11 @@ pub fn build() -> App<'static, 'static> {
.short("t")
.help("Chooses keys valid at the specified time and \
sets the signature's creation time"))
+ .arg(Arg::with_name("use-expired-subkey")
+ .long("use-expired-subkey")
+ .help("If a certificate has only expired \
+ encryption-capable subkeys, fall back \
+ to using the one that expired last"))
)
.subcommand(SubCommand::with_name("sign")