summaryrefslogtreecommitdiffstats
path: root/openpgp/src
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2020-10-21 14:44:57 +0200
committerJustus Winter <justus@sequoia-pgp.org>2020-10-21 14:44:57 +0200
commitd342e72f994a08aca89d225ee41816d4b291b2df (patch)
tree243c078205b459631cbc16c649fa58a9b075ebe7 /openpgp/src
parent8a38f0483e1bfb907f8aac7764a5094ca9068c44 (diff)
openpgp: Add KeyAmalgamationIter::supported.
- Changes the iterator to only return keys supported by Sequoia and the underlying cryptographic library. - Also add ValidKeyAmalgamationIter::supported. - Fixes #580.
Diffstat (limited to 'openpgp/src')
-rw-r--r--openpgp/src/cert/amalgamation/key/iter.rs129
1 files changed, 129 insertions, 0 deletions
diff --git a/openpgp/src/cert/amalgamation/key/iter.rs b/openpgp/src/cert/amalgamation/key/iter.rs
index 98a9e808..a41673bd 100644
--- a/openpgp/src/cert/amalgamation/key/iter.rs
+++ b/openpgp/src/cert/amalgamation/key/iter.rs
@@ -75,6 +75,10 @@ pub struct KeyAmalgamationIter<'a, P, R>
// Only return keys in this set.
key_handles: Option<Vec<KeyHandle>>,
+ // If not None, filters by whether we support the key's asymmetric
+ // algorithm.
+ supported: Option<bool>,
+
_p: std::marker::PhantomData<P>,
_r: std::marker::PhantomData<R>,
}
@@ -88,6 +92,7 @@ impl<'a, P, R> fmt::Debug for KeyAmalgamationIter<'a, P, R>
.field("secret", &self.secret)
.field("unencrypted_secret", &self.unencrypted_secret)
.field("key_handles", &self.key_handles)
+ .field("supported", &self.supported)
.finish()
}
}
@@ -166,6 +171,21 @@ impl<'a, P, R> KeyAmalgamationIter<'a, P, R>
}
}
+ if let Some(want_supported) = self.supported {
+ if ka.key().pk_algo().is_supported() {
+ // It is supported.
+ if ! want_supported {
+ t!("PK algo is supported... skipping.");
+ continue;
+ }
+ } else {
+ if want_supported {
+ t!("PK algo is not supported... skipping.");
+ continue;
+ }
+ }
+ }
+
if let Some(want_secret) = self.secret {
if ka.key().has_secret() {
// We have a secret.
@@ -221,6 +241,7 @@ impl<'a, P, R> KeyAmalgamationIter<'a, P, R>
secret: None,
unencrypted_secret: None,
key_handles: None,
+ supported: None,
_p: std::marker::PhantomData,
_r: std::marker::PhantomData,
@@ -257,6 +278,7 @@ impl<'a, P, R> KeyAmalgamationIter<'a, P, R>
secret: Some(true),
unencrypted_secret: self.unencrypted_secret,
key_handles: self.key_handles,
+ supported: self.supported,
_p: std::marker::PhantomData,
_r: std::marker::PhantomData,
@@ -293,6 +315,7 @@ impl<'a, P, R> KeyAmalgamationIter<'a, P, R>
secret: self.secret,
unencrypted_secret: Some(true),
key_handles: self.key_handles,
+ supported: self.supported,
_p: std::marker::PhantomData,
_r: std::marker::PhantomData,
@@ -390,6 +413,35 @@ impl<'a, P, R> KeyAmalgamationIter<'a, P, R>
self
}
+ /// Changes the iterator to only return a key if it is supported
+ /// by Sequoia's cryptographic backend.
+ ///
+ /// Which public key encryption algorithms Sequoia supports
+ /// depends on the cryptographic backend selected at compile time.
+ /// This filter makes sure that only supported keys are returned.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # fn main() -> sequoia_openpgp::Result<()> {
+ /// # use sequoia_openpgp as openpgp;
+ /// # use openpgp::cert::prelude::*;
+ /// # let (cert, _) =
+ /// # CertBuilder::general_purpose(None, Some("alice@example.org"))
+ /// # .generate()?;
+ /// # let mut i = 0;
+ /// for ka in cert.keys().supported() {
+ /// // Use it.
+ /// # i += 1;
+ /// }
+ /// # assert_eq!(i, 2);
+ /// # Ok(()) }
+ /// ```
+ pub fn supported(mut self) -> Self {
+ self.supported = Some(true);
+ self
+ }
+
/// Changes the iterator to only return subkeys.
///
/// This function also changes the return type. Instead of the
@@ -435,6 +487,7 @@ impl<'a, P, R> KeyAmalgamationIter<'a, P, R>
secret: self.secret,
unencrypted_secret: self.unencrypted_secret,
key_handles: self.key_handles,
+ supported: self.supported,
_p: std::marker::PhantomData,
_r: std::marker::PhantomData,
@@ -493,6 +546,7 @@ impl<'a, P, R> KeyAmalgamationIter<'a, P, R>
secret: self.secret,
unencrypted_secret: self.unencrypted_secret,
key_handles: self.key_handles,
+ supported: self.supported,
flags: None,
alive: None,
revoked: None,
@@ -609,6 +663,10 @@ pub struct ValidKeyAmalgamationIter<'a, P, R>
// Only return keys in this set.
key_handles: Option<Vec<KeyHandle>>,
+ // If not None, filters by whether we support the key's asymmetric
+ // algorithm.
+ supported: Option<bool>,
+
// If not None, only returns keys with the specified flags.
flags: Option<KeyFlags>,
@@ -634,6 +692,7 @@ impl<'a, P, R> fmt::Debug for ValidKeyAmalgamationIter<'a, P, R>
.field("secret", &self.secret)
.field("unencrypted_secret", &self.unencrypted_secret)
.field("key_handles", &self.key_handles)
+ .field("supported", &self.supported)
.field("flags", &self.flags)
.field("alive", &self.alive)
.field("revoked", &self.revoked)
@@ -742,6 +801,21 @@ impl<'a, P, R> ValidKeyAmalgamationIter<'a, P, R>
}
}
+ if let Some(want_supported) = self.supported {
+ if ka.key().pk_algo().is_supported() {
+ // It is supported.
+ if ! want_supported {
+ t!("PK algo is supported... skipping.");
+ continue;
+ }
+ } else {
+ if want_supported {
+ t!("PK algo is not supported... skipping.");
+ continue;
+ }
+ }
+ }
+
if let Some(flags) = self.flags.as_ref() {
if !ka.has_any_key_flag(flags) {
t!("Have flags: {:?}, want flags: {:?}... skipping.",
@@ -1300,6 +1374,7 @@ impl<'a, P, R> ValidKeyAmalgamationIter<'a, P, R>
secret: Some(true),
unencrypted_secret: self.unencrypted_secret,
key_handles: self.key_handles,
+ supported: self.supported,
flags: self.flags,
alive: self.alive,
revoked: self.revoked,
@@ -1346,6 +1421,7 @@ impl<'a, P, R> ValidKeyAmalgamationIter<'a, P, R>
secret: self.secret,
unencrypted_secret: Some(true),
key_handles: self.key_handles,
+ supported: self.supported,
flags: self.flags,
alive: self.alive,
revoked: self.revoked,
@@ -1454,6 +1530,39 @@ impl<'a, P, R> ValidKeyAmalgamationIter<'a, P, R>
self
}
+ /// Changes the iterator to only return a key if it is supported
+ /// by Sequoia's cryptographic backend.
+ ///
+ /// Which public key encryption algorithms Sequoia supports
+ /// depends on the cryptographic backend selected at compile time.
+ /// This filter makes sure that only supported keys are returned.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # fn main() -> sequoia_openpgp::Result<()> {
+ /// # use sequoia_openpgp as openpgp;
+ /// # use openpgp::cert::prelude::*;
+ /// # let (cert, _) =
+ /// # CertBuilder::general_purpose(None, Some("alice@example.org"))
+ /// # .generate()?;
+ /// # let mut i = 0;
+ /// use openpgp::policy::StandardPolicy;
+ ///
+ /// let p = &StandardPolicy::new();
+ ///
+ /// for ka in cert.keys().with_policy(p, None).supported() {
+ /// // Use it.
+ /// # i += 1;
+ /// }
+ /// # assert_eq!(i, 2);
+ /// # Ok(()) }
+ /// ```
+ pub fn supported(mut self) -> Self {
+ self.supported = Some(true);
+ self
+ }
+
/// Changes the iterator to skip the primary key.
///
/// This also changes the iterator's return type. Instead of
@@ -1502,6 +1611,7 @@ impl<'a, P, R> ValidKeyAmalgamationIter<'a, P, R>
secret: self.secret,
unencrypted_secret: self.unencrypted_secret,
key_handles: self.key_handles,
+ supported: self.supported,
flags: self.flags,
alive: self.alive,
revoked: self.revoked,
@@ -1671,4 +1781,23 @@ mod test {
}
}
}
+
+ #[test]
+ fn select_supported() -> crate::Result<()> {
+ use crate::types::PublicKeyAlgorithm;
+ if ! PublicKeyAlgorithm::DSA.is_supported()
+ || PublicKeyAlgorithm::ElGamalEncrypt.is_supported()
+ {
+ return Ok(()); // Skip on this backend.
+ }
+
+ let cert =
+ Cert::from_bytes(crate::tests::key("dsa2048-elgamal3072.pgp"))?;
+ assert_eq!(cert.keys().count(), 2);
+ assert_eq!(cert.keys().supported().count(), 1);
+ let p = &crate::policy::NullPolicy::new();
+ assert_eq!(cert.keys().with_policy(p, None).count(), 2);
+ assert_eq!(cert.keys().with_policy(p, None).supported().count(), 1);
+ Ok(())
+ }
}