summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@sequoia-pgp.org>2024-01-23 09:10:22 +0100
committerNeal H. Walfield <neal@sequoia-pgp.org>2024-01-23 11:14:04 +0100
commit51e75567206d9645a36b2d1df5fac1dee1279129 (patch)
treecf0fad6452e9abafe5e1eb3c060c207410ac22fc
parent7c5efa151eb99429401f871792090c0c5cf9f63e (diff)
openpgp: Add Cert::exportable.
- Add `Cert::exportable` to return whether a certificate is exportable or not. - A certificate should only be exported if it has at least one exportable direct key signature, or there is at least one user ID or user attribute with at least one exportable self-signature.
-rw-r--r--openpgp/NEWS1
-rw-r--r--openpgp/src/serialize/cert.rs59
2 files changed, 60 insertions, 0 deletions
diff --git a/openpgp/NEWS b/openpgp/NEWS
index 1ce386c5..9b8204f4 100644
--- a/openpgp/NEWS
+++ b/openpgp/NEWS
@@ -14,6 +14,7 @@
- KeyAmalgamation::valid_third_party_revocations_by_key
- Parse::from_buffered_reader
- armor::Reader::from_buffered_reader
+ - Cert::exportable
- CertBuilder::set_exportable
* Changes in 1.17.0
** Notable fixes
diff --git a/openpgp/src/serialize/cert.rs b/openpgp/src/serialize/cert.rs
index 764a16ac..3278ea2b 100644
--- a/openpgp/src/serialize/cert.rs
+++ b/openpgp/src/serialize/cert.rs
@@ -11,6 +11,65 @@ use crate::serialize::{
impl Cert {
+ /// Returns whether the certificate should be exported.
+ ///
+ /// A certificate should only be exported if it has at least one
+ /// exportable direct key signature, or there is at least one user
+ /// ID with at least one exportable self signature.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::cert::prelude::*;
+ ///
+ /// # fn main() -> openpgp::Result<()> {
+ /// // By default, certificates are exportable.
+ /// let (cert, _) =
+ /// CertBuilder::general_purpose(None, Some("alice@example.org"))
+ /// .generate()?;
+ /// assert!(cert.exportable());
+ ///
+ /// // Setting the exportable flag to false makes them
+ /// // not-exportable.
+ /// let (cert, _) =
+ /// CertBuilder::general_purpose(None, Some("alice@example.org"))
+ /// .set_exportable(false)
+ /// .generate()?;
+ /// assert!(! cert.exportable());
+ /// # Ok(())
+ /// # }
+ /// ```
+ #[allow(clippy::if_same_then_else)]
+ pub fn exportable(&self) -> bool {
+ let pk = self.primary_key();
+
+ if pk.self_signatures().chain(pk.self_revocations())
+ .any(|sig| sig.exportable().is_ok())
+ {
+ // Exportable direct key signature. Export it.
+ true
+ } else if self.userids().any(|userid| {
+ userid.self_signatures()
+ .chain(userid.self_revocations())
+ .any(|sig| sig.exportable().is_ok())
+ }) {
+ // User ID with exportable self signature. Export it.
+ true
+ } else if self.user_attributes().any(|ua| {
+ ua.self_signatures()
+ .chain(ua.self_revocations())
+ .any(|sig| sig.exportable().is_ok())
+ }) {
+ // User attribute with exportable self signature. Export
+ // it.
+ true
+ } else {
+ // Don't export it.
+ false
+ }
+ }
+
/// Serializes or exports the Cert.
///
/// If `export` is true, then non-exportable signatures are not