diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2021-06-28 15:13:27 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2021-07-16 11:57:26 +0200 |
commit | 8e2c1beb8b65a1487e046a87bbb4f27ce33e4ced (patch) | |
tree | 0ea9f3a3038fb3ce8460c171c2cbd7f7a5e1479c | |
parent | 33d4f9513627b22e4bc1c3ecf2fa22f1dd3b274f (diff) |
openpgp: Add missing ValidAmalgamation::revocation_keys.
- The documentation talks about it, but the function was missing.
-rw-r--r-- | openpgp/src/cert/amalgamation.rs | 73 | ||||
-rw-r--r-- | openpgp/src/cert/amalgamation/key.rs | 27 |
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()) + } } |