198 lines
10 KiB
Diff
198 lines
10 KiB
Diff
From b8498a61d397bee6dc5574d44041a263a5a5c0ad Mon Sep 17 00:00:00 2001
|
|
From: "Neal H. Walfield" <neal@sequoia-pgp.org>
|
|
Date: Fri, 18 Apr 2025 12:36:29 +0200
|
|
Subject: [PATCH] Change try_decrypt to take a reference to the key.
|
|
|
|
- `Helper::try_decrypt` only needs a reference to the key.
|
|
|
|
- Change it to take a reference instead of taking ownership of the
|
|
key.
|
|
---
|
|
src/commands/decrypt.rs | 13 ++++++-------
|
|
1 file changed, 6 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/src/commands/decrypt.rs b/src/commands/decrypt.rs
|
|
index 70091912..ef453743 100644
|
|
--- a/src/commands/decrypt.rs
|
|
+++ b/src/commands/decrypt.rs
|
|
@@ -8,7 +8,7 @@ use sequoia_openpgp as openpgp;
|
|
use openpgp::types::SymmetricAlgorithm;
|
|
use openpgp::fmt::hex;
|
|
use openpgp::KeyHandle;
|
|
-use openpgp::crypto::{self, SessionKey, Decryptor};
|
|
+use openpgp::crypto::{self, SessionKey};
|
|
use openpgp::{Fingerprint, Cert, KeyID, Result};
|
|
use openpgp::packet;
|
|
use openpgp::packet::prelude::*;
|
|
@@ -187,7 +187,7 @@ impl<'c, 'store, 'rstore> Helper<'c, 'store, 'rstore>
|
|
/// to decrypt the packet parser using `decrypt`.
|
|
fn try_decrypt(&self, pkesk: &PKESK,
|
|
sym_algo: Option<SymmetricAlgorithm>,
|
|
- mut keypair: Box<dyn crypto::Decryptor>,
|
|
+ keypair: &mut dyn crypto::Decryptor,
|
|
decrypt: &mut dyn FnMut(Option<SymmetricAlgorithm>, &SessionKey) -> bool)
|
|
-> Option<Option<Cert>>
|
|
{
|
|
@@ -277,10 +277,10 @@ impl<'c, 'store, 'rstore> DecryptionHelper for Helper<'c, 'store, 'rstore>
|
|
slf.vhelper.sq.decrypt_key(Some(cert), key.clone(), prompt, true)
|
|
.ok()
|
|
.and_then(|key| {
|
|
- let keypair = Box::new(key.into_keypair()
|
|
- .expect("decrypted secret key material"));
|
|
+ let mut keypair = key.into_keypair()
|
|
+ .expect("decrypted secret key material");
|
|
|
|
- slf.try_decrypt(pkesk, sym_algo, keypair, decrypt)
|
|
+ slf.try_decrypt(pkesk, sym_algo, &mut keypair, decrypt)
|
|
})
|
|
};
|
|
|
|
@@ -409,9 +409,8 @@ impl<'c, 'store, 'rstore> DecryptionHelper for Helper<'c, 'store, 'rstore>
|
|
}
|
|
}
|
|
|
|
- let keypair = Box::new(key);
|
|
if let Some(fp) = self.try_decrypt(
|
|
- &pkesk, sym_algo, keypair, decrypt)
|
|
+ &pkesk, sym_algo, &mut key, decrypt)
|
|
{
|
|
return Ok(fp);
|
|
} else {
|
|
--
|
|
2.55.0
|
|
|
|
|
|
|
|
From 7f929fc58f9ec97f409a165904fc606b579ee49c Mon Sep 17 00:00:00 2001
|
|
From: "Neal H. Walfield" <neal@sequoia-pgp.org>
|
|
Date: Fri, 18 Apr 2025 12:38:32 +0200
|
|
Subject: [PATCH] Use the password cache to unlock keys on the softkey backend.
|
|
|
|
- `--password-file` can be used to seed the password cache.
|
|
|
|
- Currently, the password cache is not used to unlock keys on the
|
|
keystore, because the keys may be protected by a retry counter,
|
|
and we can't be sure that the passwords in the cache should be
|
|
used for any given key.
|
|
|
|
- We know, however, that keys managed by the softkeys backend are
|
|
never protected by a retry counter. As such, if a key is managed
|
|
by the softkey backend, try the password cache.
|
|
|
|
- If the password cache is not empty, and a key is managed by
|
|
another backend, print a warning that the password cache is
|
|
being ignored.
|
|
|
|
- Fixes #563.
|
|
---
|
|
src/commands/decrypt.rs | 81 ++++++++++++++++++++++++++++++++++++++++-
|
|
1 file changed, 80 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/commands/decrypt.rs b/src/commands/decrypt.rs
|
|
index ef453743..086482ca 100644
|
|
--- a/src/commands/decrypt.rs
|
|
+++ b/src/commands/decrypt.rs
|
|
@@ -364,6 +364,22 @@ impl<'c, 'store, 'rstore> DecryptionHelper for Helper<'c, 'store, 'rstore>
|
|
Err(err) => {
|
|
match err.downcast() {
|
|
Ok(keystore::Error::InaccessibleDecryptionKey(keys)) => {
|
|
+ // Get a reference to the softkeys backend.
|
|
+ let mut softkeys = if let Ok(backends) = ks.backends() {
|
|
+ let mut softkeys = None;
|
|
+ for mut backend in backends.into_iter() {
|
|
+ if let Ok(id) = backend.id() {
|
|
+ if id == "softkeys" {
|
|
+ softkeys = Some(backend);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ softkeys
|
|
+ } else {
|
|
+ None
|
|
+ };
|
|
+
|
|
for key_status in keys.into_iter() {
|
|
let pkesk = key_status.pkesk().clone();
|
|
let mut key = key_status.into_key();
|
|
@@ -375,11 +391,74 @@ impl<'c, 'store, 'rstore> DecryptionHelper for Helper<'c, 'store, 'rstore>
|
|
.set_transport_encryption(),
|
|
true);
|
|
|
|
+ // If we have any cached
|
|
+ // passwords, and the key is not
|
|
+ // protected by a retry counter,
|
|
+ // try the cached passwords.
|
|
+ //
|
|
+ // Right now,we only try the
|
|
+ // password cache with keys
|
|
+ // managed by the softkeys
|
|
+ // backend, which we know are not
|
|
+ // protected by a retry counter.
|
|
+ // It would be better to query the
|
|
+ // key, but the key store doesn't
|
|
+ // expose that yet information yet
|
|
+ // so we use this heuristic for
|
|
+ // now.
|
|
+ let password_cache
|
|
+ = self.sq.password_cache.lock().unwrap();
|
|
+ if ! password_cache.is_empty() {
|
|
+ // There's currently no way to
|
|
+ // go from a key handle to the
|
|
+ // backend.
|
|
+ let mut on_softkeys = false;
|
|
+ if let Some(softkeys) = softkeys.as_mut() {
|
|
+ let devices = softkeys.devices();
|
|
+ if let Ok(devices) = devices {
|
|
+ for mut device in devices.into_iter() {
|
|
+ let keys = device.keys();
|
|
+ if let Ok(keys) = keys {
|
|
+ for mut a_key in keys.into_iter() {
|
|
+ if let Ok(a_id) = a_key.id() {
|
|
+ if key.id().ok() == Some(a_id) {
|
|
+ // Same id. We have a match.
|
|
+ on_softkeys = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if on_softkeys {
|
|
+ for password in password_cache.iter() {
|
|
+ if let Ok(()) = key.unlock(password.clone()) {
|
|
+ if let Some(fp) = self.try_decrypt(
|
|
+ &pkesk, sym_algo, &mut key, decrypt)
|
|
+ {
|
|
+ return Ok(fp);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ } else {
|
|
+ eprintln!(
|
|
+ "{}, {} is locked, but not \
|
|
+ trying cached passwords, \
|
|
+ because the key may be \
|
|
+ protected by a retry counter.",
|
|
+ keyid, userid.display());
|
|
+ }
|
|
+ }
|
|
+ drop(password_cache);
|
|
+
|
|
loop {
|
|
if self.sq.batch {
|
|
eprintln!(
|
|
"{}, {} is locked, but not \
|
|
- prompting for password, \
|
|
+ prompting for a password, \
|
|
because you passed --batch.",
|
|
keyid, userid.display());
|
|
break;
|
|
--
|
|
GitLab
|
|
|
|
|