summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2021-06-28 15:13:27 +0200
committerJustus Winter <justus@sequoia-pgp.org>2021-07-16 11:57:26 +0200
commit8e2c1beb8b65a1487e046a87bbb4f27ce33e4ced (patch)
tree0ea9f3a3038fb3ce8460c171c2cbd7f7a5e1479c
parent33d4f9513627b22e4bc1c3ecf2fa22f1dd3b274f (diff)
openpgp: Add missing ValidAmalgamation::revocation_keys.
- The documentation talks about it, but the function was missing.
-rw-r--r--openpgp/src/cert/amalgamation.rs73
-rw-r--r--openpgp/src/cert/amalgamation/key.rs27
2 files changed, 100 insertions, 0 deletions
diff --git a/openpgp/src/cert/amalgamation.rs b/openpgp/src/cert/amalgamation.rs
index 56e67f4c..a12c7b9b 100644
--- a/openpgp/src/cert/amalgamation.rs
+++ b/openpgp/src/cert/amalgamation.rs
@@ -250,6 +250,7 @@ use crate::{
Features,
HashAlgorithm,
KeyServerPreferences,
+ RevocationKey,
RevocationStatus,
SignatureType,
SymmetricAlgorithm,
@@ -607,6 +608,52 @@ pub trait ValidAmalgamation<'a, C: 'a>: seal::Sealed
/// # }
/// ```
fn revocation_status(&self) -> RevocationStatus<'a>;
+
+ /// Returns a list of any designated revokers for this component.
+ ///
+ /// This function returns the designated revokers listed on the
+ /// components's binding signatures and the certificate's direct
+ /// key signatures.
+ ///
+ /// Note: the returned list is deduplicated.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use sequoia_openpgp as openpgp;
+ /// # use openpgp::Result;
+ /// use openpgp::cert::prelude::*;
+ /// use openpgp::policy::StandardPolicy;
+ /// use openpgp::types::RevocationKey;
+ ///
+ /// # fn main() -> Result<()> {
+ /// let p = &StandardPolicy::new();
+ ///
+ /// let (alice, _) =
+ /// CertBuilder::general_purpose(None, Some("alice@example.org"))
+ /// .generate()?;
+ /// // Make Alice a designated revoker for Bob.
+ /// let (bob, _) =
+ /// CertBuilder::general_purpose(None, Some("bob@example.org"))
+ /// .set_revocation_keys(vec![(&alice).into()])
+ /// .generate()?;
+ ///
+ /// // Make sure Alice is listed as a designated revoker for Bob's
+ /// // primary user id.
+ /// assert_eq!(bob.with_policy(p, None)?.primary_userid()?
+ /// .revocation_keys().collect::<Vec<&RevocationKey>>(),
+ /// vec![&(&alice).into()]);
+ ///
+ /// // Make sure Alice is listed as a designated revoker for Bob's
+ /// // encryption subkey.
+ /// assert_eq!(bob.with_policy(p, None)?
+ /// .keys().for_transport_encryption().next().unwrap()
+ /// .revocation_keys().collect::<Vec<&RevocationKey>>(),
+ /// vec![&(&alice).into()]);
+ /// # Ok(()) }
+ /// ```
+ fn revocation_keys(&self)
+ -> Box<dyn Iterator<Item = &'a RevocationKey> + 'a>;
}
/// A certificate component, its associated data, and useful methods.
@@ -1752,6 +1799,32 @@ impl<'a, C> ValidAmalgamation<'a, C> for ValidComponentAmalgamation<'a, C> {
self.bundle._revocation_status(self.policy(), self.cert.time,
false, Some(self.binding_signature))
}
+
+ fn revocation_keys(&self)
+ -> Box<dyn Iterator<Item = &'a RevocationKey> + 'a>
+ {
+ let mut keys = std::collections::HashSet::new();
+
+ let policy = self.policy();
+ let pk_sec = self.cert().primary_key().hash_algo_security();
+
+ // All valid self-signatures.
+ let sec = self.hash_algo_security;
+ self.self_signatures()
+ .filter(move |sig| {
+ policy.signature(sig, sec).is_ok()
+ })
+ // All direct-key signatures.
+ .chain(self.cert().primary_key()
+ .self_signatures()
+ .filter(|sig| {
+ policy.signature(sig, pk_sec).is_ok()
+ }))
+ .flat_map(|sig| sig.revocation_keys())
+ .for_each(|rk| { keys.insert(rk); });
+
+ Box::new(keys.into_iter())
+ }
}
impl<'a, C> crate::cert::Preferences<'a>
diff --git a/openpgp/src/cert/amalgamation/key.rs b/openpgp/src/cert/amalgamation/key.rs
index 159348bb..11e4fc29 100644
--- a/openpgp/src/cert/amalgamation/key.rs
+++ b/openpgp/src/cert/amalgamation/key.rs
@@ -276,6 +276,7 @@ use crate::{
seal,
types::{
KeyFlags,
+ RevocationKey,
RevocationStatus,
SignatureType,
},
@@ -1238,6 +1239,32 @@ impl<'a, P, R, R2> ValidAmalgamation<'a, Key<P, R>>
true, Some(self.binding_signature))
}
}
+
+ fn revocation_keys(&self)
+ -> Box<dyn Iterator<Item = &'a RevocationKey> + 'a>
+ {
+ let mut keys = std::collections::HashSet::new();
+
+ let policy = self.policy();
+ let pk_sec = self.cert().primary_key().hash_algo_security();
+
+ // All valid self-signatures.
+ let sec = self.hash_algo_security;
+ self.self_signatures()
+ .filter(move |sig| {
+ policy.signature(sig, sec).is_ok()
+ })
+ // All direct-key signatures.
+ .chain(self.cert().primary_key()
+ .self_signatures()
+ .filter(|sig| {
+ policy.signature(sig, pk_sec).is_ok()
+ }))
+ .flat_map(|sig| sig.revocation_keys())
+ .for_each(|rk| { keys.insert(rk); });
+
+ Box::new(keys.into_iter())
+ }
}