summaryrefslogtreecommitdiffstats
path: root/openpgp/src/cert
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp/src/cert')
-rw-r--r--openpgp/src/cert/amalgamation.rs1353
-rw-r--r--openpgp/src/cert/amalgamation/iter.rs388
-rw-r--r--openpgp/src/cert/amalgamation/key.rs1937
-rw-r--r--openpgp/src/cert/amalgamation/key/iter.rs1656
-rw-r--r--openpgp/src/cert/bindings.rs40
-rw-r--r--openpgp/src/cert/builder.rs829
-rw-r--r--openpgp/src/cert/bundle.rs848
-rw-r--r--openpgp/src/cert/component_iter.rs222
-rw-r--r--openpgp/src/cert/components.rs495
-rw-r--r--openpgp/src/cert/key_amalgamation.rs909
-rw-r--r--openpgp/src/cert/keyiter.rs1075
-rw-r--r--openpgp/src/cert/mod.rs2759
-rw-r--r--openpgp/src/cert/parser/low_level/grammar.lalrpop4
-rw-r--r--openpgp/src/cert/parser/low_level/grammar.rs1
-rw-r--r--openpgp/src/cert/parser/low_level/lexer.rs4
-rw-r--r--openpgp/src/cert/parser/mod.rs743
-rw-r--r--openpgp/src/cert/prelude.rs59
-rw-r--r--openpgp/src/cert/revoke.rs858
18 files changed, 10236 insertions, 3944 deletions
diff --git a/openpgp/src/cert/amalgamation.rs b/openpgp/src/cert/amalgamation.rs
index afe84ffe..8f887166 100644
--- a/openpgp/src/cert/amalgamation.rs
+++ b/openpgp/src/cert/amalgamation.rs
@@ -1,17 +1,224 @@
-//! Component amalgamations.
+//! Components, their associated signatures, and some useful methods.
//!
-//! Whereas a `ComponentBundle` groups a `Component` with its self
-//! signatures, its third-party signatures, and its revocation
-//! certificates, an `Amalgamation` groups a `ComponentBundle` with
-//! all of the necessary context needed to correctly implement
-//! relevant functionality related to the component. Specifically, a
-//! `Amalgamation` includes a reference to the `ComponentBundle`, and
-//! a reference to the containing certificate.
+//! Whereas a [`ComponentBundle`] owns a `Component` and its
+//! associated [`Signature`]s, a [`ComponentAmalgamation`] references
+//! a `ComponentBundle` and its containing [`Cert`]. This additional
+//! context means that a `ComponentAmalgamation` can implement more of
+//! OpenPGP's high-level semantics than a `ComponentBundle` can. For
+//! instance, most of the information about a primary key, such as its
+//! capabilities, is on the primary User ID's binding signature. A
+//! `ComponentAmalgamation` can find the certificate's primary User
+//! ID; a `ComponentBundle` can't. Similarly, when looking up a
+//! subpacket, if it isn't present in the component's binding
+//! signature, then an OpenPGP implementation [is supposed to] consult
+//! the certificate's direct key signatures. A
+//! `ComponentAmalgamation` has access to this information; a
+//! `ComponentBundle` doesn't.
//!
-//! A notable differences between `ComponentBundle`s and
-//! `Amalgamation`s is that a `ComponentBundle`, owns its data, but an
-//! `Amalgamation` only references the contained data.
-use std::borrow::Borrow;
+//! Given the limitations of a `ComponentBundle`, it would seem more
+//! useful to just change it to include a reference to its containing
+//! certificate. That change would make `ComponentAmalgamation`s
+//! redundant. Unfortunately, this isn't possible, because it would
+//! result in a self-referential data structure, which Rust doesn't
+//! allow. To understand how this arises, consider a certificate `C`,
+//! which contains a `ComponentBundle` `B`. If `B` contains a
+//! reference to `C`, then `C` references itself, because `C` contains
+//! `B`!
+//!
+//! ```text
+//! Cert:[ Bundle:[ &Cert ] ]
+//! ^ |
+//! `------------'
+//! ```
+//!
+//! # Policy
+//!
+//! Although a `ComponentAmalgamation` contains the information
+//! necessary to realize high-level OpenPGP functionality, components
+//! can have multiple self signatures, and functions that consult the
+//! binding signature need to determine the best one to use. There
+//! are two main concerns here.
+//!
+//! First, we need to protect the user from forgeries. As attacks
+//! improve, cryptographic algorithms that were once considered secure
+//! now provide insufficient security margins. For instance, in 2007
+//! it was possible to find [MD5 collisions] using just a few seconds
+//! of computing time on a desktop computer. Sequoia provides a
+//! flexible mechanism, called [`Policy`] objects, that allow users to
+//! implement this type of filtering: before a self signature is used,
+//! a policy object is queried to determine whether the `Signature`
+//! should be rejected. If so, then it is skipped.
+//!
+//! Second, we need an algorithm to determine the most appropriate
+//! self signature. Obvious non-candidate self signatures are self
+//! signatures whose creation time is in the future. We don't assume
+//! that these self signatures are bad per se, but that they represent
+//! a policy that should go into effect some time in the future.
+//!
+//! We extend this idea of a self signature representing a policy for
+//! a certain period of time to all self signatures. In particular,
+//! Sequoia takes the view that *a binding signature represents a
+//! policy that is valid from its creation time until its expiry*.
+//! Thus, when considering what self signature to use, we need a
+//! reference time. Given the reference time, we then use the self
+//! signature that was in effect at that time, i.e., the most recent,
+//! non-expired, non-revoked self signature that was created at or
+//! prior to the reference time. In other words, we ignore self
+//! signatures created after the reference time. We take the position
+//! that if the certificate holder wants a new policy to apply to
+//! existing signatures, then the new self signature should be
+//! backdated, and existing self signatures revoked, if necessary.
+//!
+//! Consider evaluating a signature over a document. Sequoia's
+//! [streaming verifier] uses the signature's creation time as the
+//! reference time. Thus, if the signature was created on June 9th,
+//! 2011, then, when evaluating that signature, the streaming verifier
+//! uses a self signature that was live at that time, since that was
+//! the self signature that represented the signer's policy at the
+//! time the signature over the document was created.
+//!
+//! A consequence of this approach is that even if the self signature
+//! were considered expired at the time the signature was evaluated
+//! (e.g., "now"), this fact doesn't invalidate the signature. That
+//! is, a self siganture's lifetime does not impact a signature's
+//! lifetime; a signature's lifetime is defined by its own creation
+//! time and expiry. Similarly, a key's lifetime is defined by its
+//! own creation time and expiry.
+//!
+//! This interpretation of lifetimes removes a major disadvantage that
+//! comes with fast rotation of subkeys: if an implementation binds
+//! the lifetime of signatures to the signing key, and the key
+//! expires, then old signatures are considered invalid. Consider a
+//! user who generates a new signature subkey each week, and sets it
+//! to expire after exactly one week. If we use the policy that the
+//! signature is only valid while the key *and* the self signature are
+//! live, then if someone checks the signature a week after receiving
+//! it, the signature will be considered invalid, because the key has
+//! expired. The practical result is that all old messages from this
+//! user will be considered invalid! Unfortunately, this will result
+//! in users becoming accustomed to seeing invalid signatures, and
+//! cause them to be less suspcious of them.
+//!
+//! Sequoia's low-level mechanisms support this interpretation of self
+//! signatures, but they do *not* enforce it. It is still possible to
+//! realize other policies using this low-level API.
+//!
+//! The possibility of abuse of this interpretation of signature
+//! lifetimes is limited. If a key has been compromised, then the
+//! right thing to do is to revoke it. Expiry doesn't help: the
+//! attacker can simply create self-signatures that say whatever she
+//! wants. Assuming the secret key material has not been compromised,
+//! then an attacker could still reuse a message that would otherwise
+//! be considered expired. However, the attacker will not be able to
+//! change the signature's creation time, so, assuming a mail context
+//! and MUAs that check that the time in the message's headers matches
+//! the signature's creation time, the mails will appear old.
+//! Further, this type of attack will be mitigated by the proposed
+//! "[Intended Recipients]" subpacket, which more tightly binds the
+//! message to its context.
+//!
+//! # [`ValidComponentAmalgamation`]
+//!
+//! Most operations need to query a `ComponentAmalgamation` for
+//! multiple pieces of information. Accidentally using a different
+//! `Policy` or a different reference time for one of the queries is
+//! easy, especially when the queries are spread across multiple
+//! functions. Further, using `None` for the reference time can
+//! result in subtle timing bugs as each function translates it to the
+//! current time on demand. In these cases, the correct approach
+//! would be for the user of the library to get the current time at
+//! the start of the operation. But, this is less convenient.
+//! Finally, passing a `Policy` and a reference time to most function
+//! calls clutters the code.
+//!
+//! To mitigate these issues, we have a separate data structure,
+//! `ValidComponentAmalgamation`, which combines a
+//! `ComponetAmalgamation`, a `Policy` and a reference time. It
+//! implements methods that require a `Policy` and reference time, but
+//! instead of requiring the caller to pass them in, it uses the ones
+//! embedded in the data structure. Further, when the
+//! `ValidComponentAmalgamation` constructor is passed `None` for the
+//! reference time, it eagerly stores the current time, and uses that
+//! for all operations. This approach elegantly solves all of the
+//! aforementioned problems.
+//!
+//! # Lifetimes
+//!
+//! `ComponentAmalgamation` autoderefs to `ComponentBundle`.
+//! Unfortunately, due to the definition of the [`Deref` trait],
+//! `ComponentBundle` is assigned the same lifetime as
+//! `ComponentAmalgamation`. However, it's lifetime is actually `'a`.
+//! Particularly when using combinators like [`std::iter::map`], the
+//! `ComponentBundle`'s lifetime is longer. Consider the following
+//! code, which doesn't compile:
+//!
+//! ```compile_fail
+//! # extern crate sequoia_openpgp as openpgp;
+//! use openpgp::cert::prelude::*;
+//! use openpgp::packet::prelude::*;
+//!
+//! # let (cert, _) = CertBuilder::new()
+//! # .add_userid("Alice")
+//! # .add_signing_subkey()
+//! # .add_transport_encryption_subkey()
+//! # .generate().unwrap();
+//! cert.userids()
+//! .map(|ua| {
+//! // Use auto deref to get the containing `&ComponentBundle`.
+//! let b: &ComponentBundle<_> = &ua;
+//! b
+//! })
+//! .collect::<Vec<&UserID>>();
+//! ```
+//!
+//! Compiling it results in the following error:
+//!
+//! > `b` returns a value referencing data owned by the current
+//! > function
+//!
+//! This error occurs because the `Deref` trait says that the lifetime
+//! of the target, i.e., `&ComponentBundle`, is bounded by `ua`'s
+//! lifetime, whose lifetime is indeed limited to the closure. But,
+//! `&ComponentBundle` is independent of `ua`; it is a copy of the
+//! `ComponentAmalgamation`'s reference to the `ComponentBundle` whose
+//! lifetime is `'a`! Unfortunately, this can't be expressed using
+//! `Deref`. But, it can be done using separate methods as shown
+//! below for the [`ComponentAmalgamation::component`] method:
+//!
+//! ```
+//! # extern crate sequoia_openpgp as openpgp;
+//! use openpgp::cert::prelude::*;
+//! use openpgp::packet::prelude::*;
+//!
+//! # let (cert, _) = CertBuilder::new()
+//! # .add_userid("Alice")
+//! # .add_signing_subkey()
+//! # .add_transport_encryption_subkey()
+//! # .generate().unwrap();
+//! cert.userids()
+//! .map(|ua| {
+//! // ua's lifetime is this closure. But `component()`
+//! // returns a reference whose lifetime is that of
+//! // `cert`.
+//! ua.component()
+//! })
+//! .collect::<Vec<&UserID>>();
+//! ```
+//!
+//! [`ComponentBundle`]: ../bundle/index.html
+//! [`Signature`]: ../../packet/signature/index.html
+//! [`ComponentAmalgamation`]: struct.ComponentAmalgamation.html
+//! [`Cert`]: ../index.html
+//! [is supposed to]: https://tools.ietf.org/html/rfc4880#section-5.2.3.3
+//! [`ValidComponentAmalgamation`]: struct.ValidComponentAmalgamation.html
+//! [`std::iter::map`]: https://doc.rust-lang.org/std/iter/struct.Map.html
+//! [MD5 collisions]: https://en.wikipedia.org/wiki/MD5
+//! [`Policy`]: ../../policy/index.html
+//! [streaming verifier]: ../../parse/stream.html
+//! [Intended Recipients]: https://www.ietf.org/id/draft-ietf-openpgp-rfc4880bis-09.html#name-intended-recipient-fingerpr
+//! [signature expirations]: https://tools.ietf.org/html/rfc4880#section-5.2.3.10
+//! [`Deref` trait]: https://doc.rust-lang.org/stable/std/ops/trait.Deref.html
+//! [`ComponentAmalgamation::component`]: struct.ComponentAmalgamation.html#method.component
use std::time;
use std::time::SystemTime;
use std::clone::Clone;
@@ -19,27 +226,92 @@ use std::clone::Clone;
use crate::{
cert::prelude::*,
Error,
- packet::Signature,
+ packet::{
+ Signature,
+ Unknown,
+ UserAttribute,
+ UserID,
+ },
Result,
policy::Policy,
types::{
+ AEADAlgorithm,
+ CompressionAlgorithm,
+ Features,
+ HashAlgorithm,
+ KeyServerPreferences,
RevocationKey,
RevocationStatus,
- KeyFlags,
+ SymmetricAlgorithm,
},
};
-/// Applies a policy to an amalgamation.
+mod iter;
+pub use iter::{
+ ComponentAmalgamationIter,
+ UnknownComponentAmalgamationIter,
+ UserAttributeAmalgamationIter,
+ UserIDAmalgamationIter,
+ ValidComponentAmalgamationIter,
+ ValidUserAttributeAmalgamationIter,
+ ValidUserIDAmalgamationIter,
+};
+
+pub mod key;
+
+/// Embeds a policy and a reference time in an amalgamation.
+///
+/// This is used to turn a [`ComponentAmalgamation`] into a
+/// [`ValidComponentAmalgamation`], and a [`KeyAmalgamation`] into a
+/// [`ValidKeyAmalgamation`].
+///
+/// A certificate or a component is consider valid if:
///
-/// Note: This trait is split off from the `Amalgamation` trait, to
-/// reduce code duplication: it is often possible to provide blanket
-/// implementations of `Amalgamation`, but the `ValidateAmalgamation`
-/// trait can only be implemented on more concrete types.
+/// - It has a self signature that is live at time `t`.
+///
+/// - The policy considers it acceptable.
+///
+/// - The certificate is valid.
+///
+/// # Examples
+///
+/// ```
+/// # extern crate sequoia_openpgp as openpgp;
+/// use openpgp::cert::prelude::*;
+/// use openpgp::policy::{Policy, StandardPolicy};
+///
+/// const POLICY: &dyn Policy = &StandardPolicy::new();
+///
+/// fn f(ua: UserIDAmalgamation) -> openpgp::Result<()> {
+/// let ua = ua.with_policy(POLICY, None)?;
+/// // ...
+/// # Ok(())
+/// }
+/// # fn main() -> openpgp::Result<()> {
+/// # let (cert, _) =
+/// # CertBuilder::general_purpose(None, Some("alice@example.org"))
+/// # .generate()?;
+/// # let ua = cert.userids().nth(0).expect("User IDs");
+/// # f(ua);
+/// # Ok(())
+/// # }
+/// ```
+///
+/// [`ComponentAmalgamation`]: struct.ComponentAmalgamation.html
+/// [`ValidComponentAmalgamation`]: struct.ValidComponentAmalgamation.html
+/// [`KeyAmalgamation`]: struct.KeyAmalgamation.html
+/// [`ValidKeyAmalgamation`]: struct.ValidKeyAmalgamation.html
pub trait ValidateAmalgamation<'a, C: 'a> {
/// The type returned by `with_policy`.
+ ///
+ /// This is either a [`ValidComponentAmalgamation`] or
+ /// a [`ValidKeyAmalgamation`].
+ ///
+ /// [`ValidComponentAmalgamation`]: struct.ValidComponentAmalgamation.html
+ /// [`ValidKeyAmalgamation`]: struct.ValidKeyAmalgamation.html
type V;
- /// Changes the amalgamation's policy.
+ /// Uses the specified `Policy` and reference time with the amalgamation.
///
/// If `time` is `None`, the current time is used.
fn with_policy<T>(self, policy: &'a dyn Policy, time: T) -> Result<Self::V>
@@ -47,65 +319,55 @@ pub trait ValidateAmalgamation<'a, C: 'a> {
Self: Sized;
}
-/// An amalgamation with a policy and a reference time.
-///
-/// In a certain sense, a `ValidAmalgamation` provides a view of an
-/// `Amalgamation` as it was at a particular time. That is,
-/// signatures and components that are not valid at the reference
-/// time, because they were created after the reference time, for
-/// instance, are ignored.
+/// Applies a policy to an amalgamation.
///
-/// The methods exposed by a `ValidAmalgamation` are similar to those
-/// exposed by an `Amalgamation`, but the policy and reference time
-/// are taken from the `ValidAmalgamation`. This helps prevent using
-/// different policies or different reference times when using a
-/// component, which can easily happen when the checks span multiple
-/// functions.
-pub trait ValidAmalgamation<'a, C: 'a>
-{
- /// Returns the certificate.
- fn cert(&self) -> &'a Cert;
+/// This is an internal variant of `ValidateAmalgamation`, which
+/// allows validating a component for an otherwise invalid
+/// certificate. See `ValidComponentAmalgamation::primary` for an
+/// explanation.
+trait ValidateAmalgamationRelaxed<'a, C: 'a> {
+ /// The type returned by `with_policy`.
+ type V;
- /// Returns the amalgamation's reference time.
+ /// Changes the amalgamation's policy.
///
- /// For queries that are with respect to a point in time, this
- /// determines that point in time. For instance, if a component is
- /// created at `t_c` and expires at `t_e`, then
- /// `ValidComponentAmalgamation::alive` will return true if the reference
- /// time is greater than or equal to `t_c` and less than `t_e`.
- fn time(&self) -> SystemTime;
-
- /// Returns the amalgamation's policy.
- fn policy(&self) -> &'a dyn Policy;
-
- /// Returns the component's binding signature as of the reference time.
- fn binding_signature(&self) -> &'a Signature;
-
- /// Returns the Certificate's direct key signature as of the
- /// reference time, if any.
+ /// If `time` is `None`, the current time is used.
///
- /// Subpackets on direct key signatures apply to all components of
- /// the certificate.
- fn direct_key_signature(&self) -> Option<&'a Signature>;
-
- /// Returns the component's revocation status as of the amalgamation's
- /// reference time.
+ /// If `valid_cert` is `false`, then this does not also check
+ /// whether the certificate is valid; it only checks whether the
+ /// component is valid. Normally, this should be `true`. This
+ /// option is only expose to allow breaking an infinite recursion:
///
- /// Note: this does not return whether the certificate is valid.
- fn revoked(&self) -> RevocationStatus<'a>;
-
- /// Returns the certificate's revocation status as of the
- /// amalgamation's reference time.
- fn cert_revoked(&self) -> RevocationStatus<'a> {
- self.cert().revoked(self.policy(), self.time())
- }
-
- /// Returns whether the certificate is alive as of the
- /// amalgamation's reference time.
- fn cert_alive(&self) -> Result<()> {
- self.cert().alive(self.policy(), self.time())
- }
+ /// - To check if a certificate is valid, we check if the
+ /// primary key is valid.
+ ///
+ /// - To check if the primary key is valid, we need the primary
+ /// key's self signature
+ ///
+ /// - To find the primary key's self signature, we need to find
+ /// the primary user id
+ ///
+ /// - To find the primary user id, we need to check if the user
+ /// id is valid.
+ ///
+ /// - To check if the user id is valid, we need to check that
+ /// the corresponding certificate is valid.
+ fn with_policy_relaxed<T>(self, policy: &'a dyn Policy, time: T,
+ valid_cert: bool) -> Result<Self::V>
+ where T: Into<Option<time::SystemTime>>,
+ Self: Sized;
+}
+/// Methods for valid amalgamations.
+///
+/// The methods exposed by a `ValidComponentAmalgamation` are similar
+/// to those exposed by a `ComponentAmalgamation`, but the policy and
+/// reference time are included in the `ValidComponentAmalgamation`.
+/// This helps prevent using different policies or different reference
+/// times when using a component, which can easily happen when the
+/// checks span multiple functions.
+pub trait ValidAmalgamation<'a, C: 'a>
+{
/// Maps the given function over binding and direct key signature.
///
/// Makes `f` consider both the binding signature and the direct
@@ -116,132 +378,279 @@ pub trait ValidAmalgamation<'a, C: 'a>
/// [Section 5.2.3.3 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.3
fn map<F: Fn(&'a Signature) -> Option<T>, T>(&self, f: F) -> Option<T> {
f(self.binding_signature())
- .or_else(|| self.direct_key_signature().and_then(f))
+ .or_else(|| self.direct_key_signature().ok().and_then(f))
}
- /// Returns the key's key flags as of the amalgamation's
- /// reference time.
+ /// Returns the valid amalgamation's associated certificate.
///
- /// Considers both the binding signature and the direct key
- /// signature. Information in the binding signature takes
- /// precedence over the direct key signature. See also [Section
- /// 5.2.3.3 of RFC 4880].
+ /// # Examples
///
- /// [Section 5.2.3.3 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.3
- fn key_flags(&self) -> Option<KeyFlags> {
- self.map(|s| s.key_flags())
- }
+ /// ```
+ /// # extern crate sequoia_openpgp as openpgp;
+ /// # use openpgp::cert::prelude::*;
+ /// # use openpgp::policy::StandardPolicy;
+ /// #
+ /// fn f(ua: &ValidUserIDAmalgamation) {
+ /// let cert = ua.cert();
+ /// // ...
+ /// }
+ /// # fn main() -> openpgp::Result<()> {
+ /// # let p = &StandardPolicy::new();
+ /// # let (cert, _) =
+ /// # CertBuilder::general_purpose(None, Some("alice@example.org"))
+ /// # .generate()?;
+ /// # let fpr = cert.fingerprint();
+ /// # let ua = cert.userids().nth(0).expect("User IDs");
+ /// # assert_eq!(ua.cert().fingerprint(), fpr);
+ /// # f(&ua.with_policy(p, None)?);
+ /// # Ok(())
+ /// # }
+ /// ```
+ fn cert(&self) -> &ValidCert<'a>;
- /// Returns whether the key has at least one of the specified key
- /// flags as of the amalgamation's reference time.
+ /// Returns the amalgamation's reference time.
///
- /// Key flags are computed as described in
- /// [`key_flags()`](#method.key_flags).
- fn has_any_key_flag<F>(&self, flags: F) -> bool
- where F: Borrow<KeyFlags>
- {
- let our_flags = self.key_flags().unwrap_or_default();
- !(&our_flags & flags.borrow()).is_empty()
- }
-
- /// Returns whether key is certification capable as of the
- /// amalgamtion's reference time.
+ /// # Examples
///
- /// Key flags are computed as described in
- /// [`key_flags()`](#method.key_flags).
- fn for_certification(&self) -> bool {
- self.has_any_key_flag(KeyFlags::default().set_certification(true))
- }
+ /// ```
+ /// # use std::time::{SystemTime, Duration, UNIX_EPOCH};
+ /// #
+ /// # extern crate sequoia_openpgp as openpgp;
+ /// # use openpgp::cert::prelude::*;
+ /// # use openpgp::policy::StandardPolicy;
+ /// fn f(ua: &ValidUserIDAmalgamation) {
+ /// let t = ua.time();
+ /// // ...
+ /// }
+ /// # fn main() -> openpgp::Result<()> {
+ /// # let p = &StandardPolicy::new();
+ /// # let t = UNIX_EPOCH + Duration::from_secs(1554542220);
+ /// # let (cert, _) =
+ /// # CertBuilder::general_purpose(None, Some("alice@example.org"))
+ /// # .set_creation_time(t)
+ /// # .generate()?;
+ /// # let ua = cert.userids().nth(0).expect("User IDs");
+ /// # let ua = ua.with_policy(p, t)?;
+ /// # assert_eq!(t, ua.time());
+ /// # f(&ua);
+ /// # Ok(())
+ /// # }
+ /// ```
+ fn time(&self) -> SystemTime;
- /// Returns whether key is signing capable as of the amalgamation's
- /// reference time.
+ /// Returns the amalgamation's policy.
///
- /// Key flags are computed as described in
- /// [`key_flags()`](#method.key_flags).
- fn for_signing(&self) -> bool {
- self.has_any_key_flag(KeyFlags::default().set_signing(true))
- }
-
- /// Returns whether key is authentication capable as of the
- /// amalgamation's reference time.
+ /// # Examples
///
- /// Key flags are computed as described in
- /// [`key_flags()`](#method.key_flags).
- fn for_authentication(&self) -> bool
- {
- self.has_any_key_flag(KeyFlags::default().set_authentication(true))
- }
+ /// ```
+ /// # extern crate sequoia_openpgp as openpgp;
+ /// # use openpgp::cert::prelude::*;
+ /// # use openpgp::policy::{Policy, StandardPolicy};
+ /// #
+ /// fn f(ua: &ValidUserIDAmalgamation) {
+ /// let policy = ua.policy();
+ /// // ...
+ /// }
+ /// # fn main() -> openpgp::Result<()> {
+ /// # let p: &dyn Policy = &StandardPolicy::new();
+ /// # let (cert, _) =
+ /// # CertBuilder::general_purpose(None, Some("alice@example.org"))
+ /// # .generate()?;
+ /// # let ua = cert.userids().nth(0).expect("User IDs");
+ /// # let ua = ua.with_policy(p, None)?;
+ /// # assert!(std::ptr::eq(p, ua.policy()));
+ /// # f(&ua);
+ /// # Ok(())
+ /// # }
+ /// ```
+ fn policy(&self) -> &'a dyn Policy;
- /// Returns whether key is intended for storage encryption as of
- /// the amalgamation's reference time.
+ /// Returns the component's binding signature as of the reference time.
///
- /// Key flags are computed as described in
- /// [`key_flags()`](#method.key_flags).
- fn for_storage_encryption(&self) -> bool
- {
- self.has_any_key_flag(KeyFlags::default().set_storage_encryption(true))
- }
-
- /// Returns whether key is intended for transport encryption as of the
- /// amalgamtion's reference time.
+ /// # Examples
///
- /// Key flags are computed as described in
- /// [`key_flags()`](#method.key_flags).
- fn for_transport_encryption(&self) -> bool
- {
- self.has_any_key_flag(KeyFlags::default().set_transport_encryption(true))
- }
+ /// ```
+ /// # extern crate sequoia_openpgp as openpgp;
+ /// # use openpgp::cert::prelude: