summaryrefslogtreecommitdiffstats
path: root/openpgp/src/packet/signature.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp/src/packet/signature.rs')
-rw-r--r--openpgp/src/packet/signature.rs3054
1 files changed, 3054 insertions, 0 deletions
diff --git a/openpgp/src/packet/signature.rs b/openpgp/src/packet/signature.rs
new file mode 100644
index 00000000..626e85ee
--- /dev/null
+++ b/openpgp/src/packet/signature.rs
@@ -0,0 +1,3054 @@
+//! Signature-related functionality.
+//!
+//! Signatures are one of the central data structures in OpenPGP.
+//! They are used to protect the integrity of both structured
+//! documents (e.g., timestamps) and unstructured documents (arbitrary
+//! byte sequences) as well as cryptographic data structures.
+//!
+//! The use of signatures to protect cryptographic data structures is
+//! central to making it easy to change an OpenPGP certificate.
+//! Consider how a certificate is initially authenticated. A user,
+//! say Alice, securely communicates her certificate's fingerprint to
+//! another user, say Bob. Alice might do this by personally handing
+//! Bob a business card with her fingerprint on it. When Bob is in
+//! front of his computer, he may then record that Alice uses the
+//! specified key. Technically, the fingerprint that he used only
+//! identifies the primary key: a fingerprint is the hash of the
+//! primary key; it does not say anything about any of the rest of the
+//! certificate---the subkeys, the User IDs, and the User Attributes.
+//! But, because these components are signed by the primary key, we
+//! know that the controller of the key intended that they be
+//! associated with the certificate. This mechanism makes it not only
+//! possible to add and revoke components, but also to change
+//! meta-data, such as a key's expiration time. If the fingerprint
+//! were instead computed over the whole OpenPGP certificate, then
+//! changing the certificate would result in a new fingerprint. In
+//! that case, the fingerprint could not be used as a long-term,
+//! unique, and stable identifier.
+//!
+//! Signatures are described in [Section 5.2 of RFC 4880].
+//!
+//! # Data Types
+//!
+//! The main signature-related data type is the [`Signature`] enum.
+//! This enum abstracts away the differences between the signature
+//! formats (the deprecated [version 3], the current [version 4], and
+//! the proposed [version 5] formats). Nevertheless some
+//! functionality remains format specific. For instance, version 4
+//! signatures introduced support for storing arbitrary key-value
+//! pairs (so-called [notations]).
+//!
+//! This version of Sequoia only supports version 4 signatures
+//! ([`Signature4`]). However, future versions may include limited
+//! support for version 3 signatures to allow working with archived
+//! messages, and we intend to add support for version 5 signatures
+//! once the new version of the specification has been finalized.
+//!
+//! When signing a document, a `Signature` is typically created
+//! indirectly by the [streaming `Signer`]. Similarly, a `Signature`
+//! packet is created as a side effect of parsing a signed message
+//! using the [`PacketParser`].
+//!
+//! The [`SigntaureBuilder`] can be used to create a binding
+//! signature, a certification, etc. The motivation for having a
+//! separate data structure for creating signatures is that it
+//! decreases the chance that a half-constructed signature is
+//! accidentally exported. When modifying an existing signature, you
+//! can use, for instance, `SignatureBuilder::from` to convert a
+//! `Signtaure` into a `SigntaureBuilder`:
+//!
+//! ```
+//! use sequoia_openpgp as openpgp;
+//! use openpgp::policy::StandardPolicy;
+//! # use openpgp::cert::prelude::*;
+//! # use openpgp::packet::prelude::*;
+//!
+//! # fn main() -> openpgp::Result<()> {
+//! let p = &StandardPolicy::new();
+//!
+//! # // Generate a new certificate. It has secret key material.
+//! # let (cert, _) = CertBuilder::new()
+//! # .generate()?;
+//! #
+//! // Create a new direct key signature using the current one as a template.
+//! let pk = cert.with_policy(p, None)?.primary_key();
+//! let sig = pk.direct_key_signature()?;
+//! let builder: SignatureBuilder = sig.clone().into();
+//! # Ok(())
+//! # }
+//! ```
+//!
+//! For version 4 signatures, attributes are set using so-called
+//! subpackets. Subpackets can be stored in two places: either in the
+//! so-called hashed area or in the so-called unhashed area. Whereas
+//! the hashed area's integrity is protected by the signature, the
+//! unhashed area is not. Because an attacker can modify the unhashed
+//! area without detection, the unhashed area should only be used for
+//! storing self-authenticating data, e.g., the issuer, or a back
+//! signature. It is also sometimes used for [hints].
+//! [`Signature::normalize`] removes unexpected subpackets from the
+//! unhashed area. However, due to a lack of context, it does not
+//! validate the remaining subpackets.
+//!
+//! In Sequoia, each subpacket area is represented by a
+//! [`SubpacketArea`] data structure. The two subpacket areas are
+//! unified by the [`SubpacketAreas`] data structure, which implements
+//! a reasonable policy for looking up subpackets. In particular, it
+//! prefers subpackets from the hashed subpacket area, and only
+//! consults the unhashed subpacket area for certain packets. See
+//! [its documentation] for details.
+//!
+//! [Section 5.2 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2
+//! [`Signature`]: ../enum.Signature.html
+//! [version 3]: https://tools.ietf.org/html/rfc1991#section-5.2.2
+//! [version 4]: https://tools.ietf.org/html/rfc4880#section-5.2.3
+//! [version 5]: https://www.ietf.org/id/draft-ietf-openpgp-rfc4880bis-09.html#name-version-4-and-5-signature-p
+//! [notations]: https://tools.ietf.org/html/rfc4880#section-5.2.3.16
+//! [`Signature4`]: struct.Signature4.html
+//! [streaming `Signer`]: ../../serialize/stream/struct.Signer.html
+//! [`PacketParser`]: ../../parse/index.html
+//! [`SigntaureBuilder`]: struct.SignatureBuilder.html
+//! [hints]: https://tools.ietf.org/html/rfc4880#section-5.13
+//! [`Signature::normalize`]: ../enum.Signature.html#method.normalize
+//! [`SubpacketArea`]: subpacket/struct.SubpacketArea.html
+//! [`SubpacketAreas`]: subpacket/struct.SubpacketAreas.html
+//! [its documentation]: subpacket/struct.SubpacketAreas.html
+
+use std::cmp::Ordering;
+use std::fmt;
+use std::ops::{Deref, DerefMut};
+use std::time::SystemTime;
+
+#[cfg(test)]
+use quickcheck::{Arbitrary, Gen};
+
+use crate::Error;
+use crate::Result;
+use crate::crypto::{
+ mpi,
+ hash::{self, Hash},
+ Signer,
+};
+use crate::HashAlgorithm;
+use crate::PublicKeyAlgorithm;
+use crate::SignatureType;
+use crate::packet::Signature;
+use crate::packet::{
+ key,
+ Key,
+};
+use crate::packet::UserID;
+use crate::packet::UserAttribute;
+use crate::Packet;
+use crate::packet;
+use crate::packet::signature::subpacket::{
+ SubpacketArea,
+ SubpacketAreas,
+ SubpacketTag,
+};
+
+#[cfg(test)]
+/// Like quickcheck::Arbitrary, but bounded.
+trait ArbitraryBounded {
+ /// Generates an arbitrary value, but only recurses if `depth >
+ /// 0`.
+ fn arbitrary_bounded<G: Gen>(g: &mut G, depth: usize) -> Self;
+}
+
+#[cfg(test)]
+/// Default depth when implementing Arbitrary using ArbitraryBounded.
+const DEFAULT_ARBITRARY_DEPTH: usize = 2;
+
+#[cfg(test)]
+macro_rules! impl_arbitrary_with_bound {
+ ($typ:path) => {
+ impl Arbitrary for $typ {
+ fn arbitrary<G: Gen>(g: &mut G) -> Self {
+ Self::arbitrary_bounded(
+ g,
+ crate::packet::signature::DEFAULT_ARBITRARY_DEPTH)
+ }
+ }
+ }
+}
+
+pub mod subpacket;
+
+/// How many seconds to backdate signatures.
+///
+/// When creating certificates (more specifically, binding
+/// signatures), and when updating binding signatures (creating
+/// signatures from templates), we backdate the signatures by this
+/// amount if no creation time is explicitly given. Backdating the
+/// certificate by a minute has the advantage that the certificate can
+/// immediately be customized:
+///
+/// In order to reliably override a binding signature, the
+/// overriding binding signature must be newer than the existing
+/// signature. If, however, the existing signature is created
+/// `now`, any newer signature must have a future creation time,
+/// and is considered invalid by Sequoia. To avoid this, we
+/// backdate certificate creation times (and hence binding
+/// signature creation times), so that there is "space" between
+/// the creation time and now for signature updates.
+pub(crate) const SIG_BACKDATE_BY: u64 = 60;
+
+/// The data stored in a `Signature` packet.
+///
+/// This data structure contains exactly those fields that appear in a
+/// [`Signature` packet]. It is used by both the [`Signature4`] and
+/// the [`SignatureBuilder`] data structures, which include other
+/// auxiliary information. This data structure is public so that
+/// `Signature4` and `SignatureBuilder` can deref to it.
+///
+/// A `SignatureField` derefs to a [`SubpacketAreas`].
+///
+/// [`Signature`]: https://tools.ietf.org/html/rfc4880#section-5.2
+/// [`Signature4`]: struct.Signature4.html
+/// [`SignatureBuilder`]: struct.SignatureBuilder.html
+/// [`SubpacketAreas`]: subpacket/struct.SubpacketAreas.html
+#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
+pub struct SignatureFields {
+ /// Version of the signature packet. Must be 4.
+ version: u8,
+ /// Type of signature.
+ typ: SignatureType,
+ /// Public-key algorithm used for this signature.
+ pk_algo: PublicKeyAlgorithm,
+ /// Hash algorithm used to compute the signature.
+ hash_algo: HashAlgorithm,
+ /// Subpackets.
+ subpackets: SubpacketAreas,
+}
+
+#[cfg(test)]
+impl ArbitraryBounded for SignatureFields {
+ fn arbitrary_bounded<G: Gen>(g: &mut G, depth: usize) -> Self {
+ SignatureFields {
+ // XXX: Make this more interesting once we dig other
+ // versions.
+ version: 4,
+ typ: Arbitrary::arbitrary(g),
+ pk_algo: PublicKeyAlgorithm::arbitrary_for_signing(g),
+ hash_algo: Arbitrary::arbitrary(g),
+ subpackets: ArbitraryBounded::arbitrary_bounded(g, depth),
+ }
+ }
+}
+
+#[cfg(test)]
+impl_arbitrary_with_bound!(SignatureFields);
+
+impl Deref for SignatureFields {
+ type Target = SubpacketAreas;
+
+ fn deref(&self) -> &Self::Target {
+ &self.subpackets
+ }
+}
+
+impl DerefMut for SignatureFields {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.subpackets
+ }
+}
+
+impl SignatureFields {
+ /// Gets the version.
+ pub fn version(&self) -> u8 {
+ self.version
+ }
+
+ /// Gets the signature type.
+ ///
+ /// This function is called `typ` and not `type`, because `type`
+ /// is a reserved word.
+ pub fn typ(&self) -> SignatureType {
+ self.typ
+ }
+
+ /// Gets the public key algorithm.
+ ///
+ /// This is `pub(crate)`, because it shouldn't be exported by
+ /// `SignatureBuilder` where it is only set at the end.
+ pub(crate) fn pk_algo(&self) -> PublicKeyAlgorithm {
+ self.pk_algo
+ }
+
+ /// Gets the hash algorithm.
+ pub fn hash_algo(&self) -> HashAlgorithm {
+ self.hash_algo
+ }
+}
+
+/// A Signature builder.
+///
+/// The `SignatureBuilder` is used to create [`Signature`]s. Although
+/// it can be used to generate a signature over a document (using
+/// [`SignatureBuilder::sign_message`]), it is usually better to use
+/// the [streaming `Signer`] for that.
+///
+/// [`Signature`]: ../enum.Signature.html
+/// [streaming `Signer`]: ../../serialize/stream/struct.Signer.html
+/// [`SignatureBuilder::sign_message`]: #method.sign_message
+///
+/// Oftentimes, you won't want to create a new signature from scratch,
+/// but modify a copy of an existing signature. This is
+/// straightforward to do since `SignatureBuilder` implements [`From`]
+/// for Signature.
+///
+/// [`From`]: https://doc.rust-lang.org/stable/std/convert/trait.From.html
+///
+/// According to [Section 5.2.3.4 of RFC 4880], `Signatures` must
+/// include a [`Signature Creation Time`] subpacket. Since this
+/// should usually be set to the current time, and is easy to forget
+/// to update, we remove any `Signature Creation Time` subpackets
+/// from both the hashed subpacket area and the unhashed subpacket
+/// area when converting a `Signature` to a `SignatureBuilder`, and
+/// when the `SignatureBuilder` is finalized, we automatically insert
+/// a `Signature Creation Time` subpacket into the hashed subpacket
+/// area unless the `Signature Creation Time` subpacket has been set
+/// using the [`set_signature_creation_time`] method or preserved
+/// using the [`preserve_signature_creation_time`] method or
+/// suppressed using the [`suppress_signature_creation_time`] method.
+///
+/// If the `SignatureBuilder` has been created from scratch, the
+/// current time is used as signature creation time. If it has been
+/// created from a template, we make sure that the generated signature
+/// is newer. If that is not possible (i.e. the generated signature
+/// would have a future creation time), the signing operation fails.
+/// This ensures that binding signatures can be updated by deriving a
+/// `SignatureBuilder` from the existing binding. To disable this,
+/// explicitly set a signature creation time, or preserve the original
+/// one, or suppress the insertion of a timestamp.
+///
+/// [Section 5.2.3.4 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.4
+/// [`Signature Creation Time`]: https://tools.ietf.org/html/rfc4880#section-5.2.3.4
+/// [`set_signature_creation_time`]: #method.set_signature_creation_time
+/// [`preserve_signature_creation_time`]: #method.preserve_signature_creation_time
+/// [`suppress_signature_creation_time`]: #method.suppress_signature_creation_time
+///
+/// Similarly, most OpenPGP implementations cannot verify a signature
+/// if neither the [`Issuer`] subpacket nor the [`Issuer Fingerprint`]
+/// subpacket has been correctly set. To avoid subtle bugs due to the
+/// use of a stale `Issuer` subpacket or a stale `Issuer Fingerprint`
+/// subpacket, we remove any `Issuer` subpackets, and `Issuer
+/// Fingerprint` subpackets from both the hashed and unhashed areas
+/// when converting a `Signature` to a `SigantureBuilder`. Since the
+/// [`Signer`] passed to the finalization routine contains the
+/// required information, we also automatically add appropriate
+/// `Issuer` and `Issuer Fingerprint` subpackets to the unhashed
+/// subpacket area when the `SignatureBuilder` is finalized unless an
+/// `Issuer` subpacket or an `IssuerFingerprint` subpacket has been
+/// added to either of the subpacket areas (which can be done using
+/// the [`set_issuer`] method and the [`set_issuer_fingerprint`]
+/// method, respectively).
+///
+/// [`Issuer`]: https://tools.ietf.org/html/rfc4880#section-5.2.3.5
+/// [`Issuer Fingerprint`]: https://www.ietf.org/id/draft-ietf-openpgp-rfc4880bis-09.html#section-5.2.3.28
+/// [`Signer`]: ../../crypto/trait.Signer.html
+/// [`set_issuer`]: #method.set_issuer
+/// [`set_issuer_fingerprint`]: #method.set_issuer_fingerprint
+///
+/// To finalize the builder, call [`sign_hash`], [`sign_message`],
+/// [`sign_direct_key`], [`sign_subkey_binding`],
+/// [`sign_primary_key_binding`], [`sign_userid_binding`],
+/// [`sign_user_attribute_binding`], [`sign_standalone`], or
+/// [`sign_timestamp`], as appropriate. These functions turn the
+/// `SignatureBuilder` into a valid `Signature`.
+///
+/// [`sign_hash`]: #method.sign_hash
+/// [`sign_message`]: #method.sign_message
+/// [`sign_direct_key`]: #method.sign_direct_key
+/// [`sign_subkey_binding`]: #method.sign_subkey_binding
+/// [`sign_primary_key_binding`]: #method.sign_primary_key_binding
+/// [`sign_userid_binding`]: #method.sign_userid_binding
+/// [`sign_user_attribute_binding`]: #method.sign_user_attribute_binding
+/// [`sign_standalone`]: #method.sign_standalone
+/// [`sign_timestamp`]: #method.sign_timestamp
+///
+/// This structure `Deref`s to its containing [`SignatureFields`]
+/// structure, which in turn `Deref`s to its subpacket areas
+/// (a [`SubpacketAreas`]).
+///
+/// [`SignatureFields`]: struct.SignatureFields.html
+/// [`SubpacketAreas`]: subpacket/struct.SubpacketAreas.html
+///
+/// # Examples
+///
+/// Update a certificate's feature set by updating the `Features`
+/// subpacket on any direct key signature, and any User ID binding
+/// signatures. See the [`Preferences`] trait for how preferences
+/// like these are looked up.
+///
+/// [`Preferences`]: ../../cert/trait.Preferences.html
+///
+/// ```
+/// use sequoia_openpgp as openpgp;
+/// use openpgp::cert::prelude::*;
+/// use openpgp::packet::prelude::*;
+/// use openpgp::packet::signature::subpacket::{Subpacket, SubpacketValue};
+/// use openpgp::policy::StandardPolicy;
+/// use openpgp::types::Features;
+///
+/// # fn main() -> openpgp::Result<()> {
+/// let p = &StandardPolicy::new();
+///
+/// let (cert, _) = CertBuilder::new().add_userid("Alice").generate()?;
+///
+/// // Derive a signer (the primary key is always certification capable).
+/// let pk = cert.primary_key().key();
+/// let mut signer = pk.clone().parts_into_secret()?.into_keypair()?;
+///
+/// let mut sigs = Vec::new();
+///
+/// let vc = cert.with_policy(p, None)?;
+///
+/// if let Ok(sig) = vc.direct_key_signature() {
+/// sigs.push(SignatureBuilder::from(sig.clone())
+/// .modify_hashed_area(|mut a| {
+/// a.replace(Subpacket::new(
+/// SubpacketValue::Features(Features::sequoia().set(10)),
+/// false)?)?;
+/// Ok(a)
+/// })?
+/// // Update the direct key signature.
+/// .sign_direct_key(&mut signer, pk)?);
+/// }
+///
+/// for ua in vc.userids() {
+/// sigs.push(SignatureBuilder::from(ua.binding_signature().clone())
+/// .modify_hashed_area(|mut a| {
+/// a.replace(Subpacket::new(
+/// SubpacketValue::Features(Features::sequoia().set(10)),
+/// false)?)?;
+/// Ok(a)
+/// })?
+/// // Update the binding signature.
+/// .sign_userid_binding(&mut signer, pk, ua.userid())?);
+/// }
+///
+/// // Merge in the new signatures.
+/// let cert = cert.merge_packets(sigs.into_iter().map(Packet::from))?;
+/// # assert_eq!(cert.bad_signatures().len(), 0);
+/// # Ok(())
+/// # }
+/// ```
+// IMPORTANT: If you add fields to this struct, you need to explicitly
+// IMPORTANT: implement PartialEq, Eq, and Hash.
+#[derive(Clone, Hash, PartialEq, Eq)]
+pub struct SignatureBuilder {
+ overrode_creation_time: bool,
+ original_creation_time: Option<SystemTime>,
+ fields: SignatureFields,
+}
+
+impl Deref for SignatureBuilder {
+ type Target = SignatureFields;
+
+ fn deref(&self) -> &Self::Target {
+ &self.fields
+ }
+}
+
+impl DerefMut for SignatureBuilder {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.fields
+ }
+}
+
+impl SignatureBuilder {
+ /// Returns a new `SignatureBuilder` object.
+ pub fn new(typ: SignatureType) -> Self {
+ SignatureBuilder {
+ overrode_creation_time: false,
+ original_creation_time: None,
+ fields: SignatureFields {
+ version: 4,
+ typ,
+ pk_algo: PublicKeyAlgorithm::Unknown(0),
+ hash_algo: HashAlgorithm::default(),
+ subpackets: SubpacketAreas::default(),
+ }
+ }
+ }
+
+ /// Sets the signature type.
+ pub fn set_type(mut self, t: SignatureType) -> Self {
+ self.typ = t;
+ self
+ }
+
+ /// Sets the hash algorithm.
+ pub fn set_hash_algo(mut self, h: HashAlgorithm) -> Self {
+ self.hash_algo = h;
+ self
+ }
+
+ /// Generates a standalone signature.
+ ///
+ /// A [Standalone Signature] ([`SignatureType::Standalone`]) is a
+ /// self-contained signature, which is only over the signature
+ /// packet.
+ ///
+ /// [Standalone Signature]: https://tools.ietf.org/html/rfc4880#section-5.2.1
+ /// [`SignatureType::Standalone`]: ../../types/enum.SignatureType.html#variant.Standalone
+ ///
+ /// This function checks that the [signature type] (passed to
+ /// [`SignatureBuilder::new`], set via
+ /// [`SignatureBuilder::set_type`], or copied when using
+ /// `SignatureBuilder::From`) is [`SignatureType::Standalone`] or
+ /// [`SignatureType::Unknown`].
+ ///
+ /// [signature type]: ../../types/enum.SignatureType.html
+ /// [`SignatureBuilder::new`]: #method.new
+ /// [`SignatureBuilder::set_type`]: #method.set_type
+ /// [`SignatureType::Timestamp`]: ../../types/enum.SignatureType.html#variant.Timestamp
+ /// [`SignatureType::Unknown`]: ../../types/enum.SignatureType.html#variant.Unknown
+ ///
+ /// The [`Signature`]'s public-key algorithm field is set to the
+ /// algorithm used by `signer`.
+ ///
+ /// [`Signature`]: ../enum.Signature.html
+ ///
+ /// If neither an [`Issuer`] subpacket (set using
+ /// [`SignatureBuilder::set_issuer`], for instance) nor an
+ /// [`Issuer Fingerprint`] subpacket (set using
+ /// [`SignatureBuilder::set_issuer_fingerprint`], for instance) is
+ /// set, they are both added to the new `Signature`'s unhashed
+ /// subpacket area and set to the `signer`'s `KeyID` and
+ /// `Fingerprint`, respectively.
+ ///
+ /// [`Issuer`]: https://tools.ietf.org/html/rfc4880#section-5.2.3.5
+ /// [`SignatureBuilder::set_issuer`]: #method.set_issuer
+ /// [`Issuer Fingerprint`]: https://www.ietf.org/id/draft-ietf-openpgp-rfc4880bis-09.html#section-5.2.3.28
+ /// [`SignatureBuilder::set_issuer_fingerprint`]: #method.set_issuer_fingerprint
+ ///
+ /// Likewise, a [`Signature Creation Time`] subpacket set to the
+ /// current time is added to the hashed area if the `Signature
+ /// Creation Time` subpacket hasn't been set using, for instance,
+ /// the [`set_signature_creation_time`] method or the
+ /// [`preserve_signature_creation_time`] method.
+ ///
+ /// [`Signature Creation Time`]: https://tools.ietf.org/html/rfc4880#section-5.2.3.4
+ /// [`set_signature_creation_time`]: #method.set_signature_creation_time
+ /// [`preserve_signature_creation_time`]: #method.preserve_signature_creation_time
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::cert::prelude::*;
+ /// use openpgp::packet::prelude::*;
+ /// use openpgp::policy::StandardPolicy;
+ /// use openpgp::types::SignatureType;
+ ///
+ /// # fn main() -> openpgp::Result<()> {
+ /// let p = &StandardPolicy::new();
+ ///
+ /// let (cert, _) = CertBuilder::new().add_signing_subkey().generate()?;
+ ///
+ /// // Get a usable (alive, non-revoked) signing key.
+ /// let key : &Key<_, _> = cert
+ /// .keys().with_policy(p, None)
+ /// .for_signing().alive().revoked(false).nth(0).unwrap().key();
+ /// // Derive a signer.
+ /// let mut signer = key.clone().parts_into_secret()?.into_keypair()?;
+ ///
+ /// let sig = SignatureBuilder::new(SignatureType::Standalone)
+ /// .sign_standalone(&mut signer)?;
+ ///
+ /// // Verify it.
+ /// sig.verify_standalone(signer.public())?;
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn sign_standalone(mut self, signer: &mut dyn Signer)
+ -> Result<Signature>
+ {
+ match self.typ {
+ SignatureType::Standalone => (),
+ SignatureType::Unknown(_) => (),
+ _ => return Err(Error::UnsupportedSignatureType(self.typ).into()),
+ }
+
+ self = self.pre_sign(signer)?;
+
+ let digest = Signature::hash_standalone(&self)?;
+
+ self.sign(signer, digest)
+ }
+
+ /// Generates a Timestamp Signature.
+ ///
+ /// Like a [Standalone Signature] (created using
+ /// [`SignatureBuilder::sign_standalone`]), a [Timestamp
+ /// Signature] is a self-contained signature, but its emphasis in
+ /// on the contained timestamp, specifically, the timestamp stored
+ /// in the [`Signature Creation Time`] subpacket. This type of
+ /// signature is primarily used by [timestamping services]. To
+ /// timestamp a signature, you can include either a [Signature
+ /// Target subpacket] (set using
+ /// [`SignatureBuilder::set_signature_target`]), or an [Embedded
+ /// Signature] (set using
+ /// [`SignatureBuilder::set_embedded_signature`]) in the hashed
+ /// area.
+ ///
+ ///
+ /// [Standalone Signature]: https://tools.ietf.org/html/rfc4880#section-5.2.1
+ /// [`SignatureBuilder::sign_standalone`]: #method.sign_standalone
+ /// [Timestamp Signature]: https://tools.ietf.org/html/rfc4880#section-5.2.1
+ /// [`Signature Creation Time`]: https://tools.ietf.org/html/rfc4880#section-5.2.3.4
+ /// [timestamping services]: https://en.wikipedia.org/wiki/Trusted_timestamping
+ /// [Signature Target subpacket]: https://tools.ietf.org/html/rfc4880#section-5.2.3.25
+ /// [`SignatureBuilder::set_signature_target`]: #method.set_signature_target
+ /// [Embedded Signature]: https://tools.ietf.org/html/rfc4880#section-5.2.3.26
+ /// [`SignatureBuilder::set_embedded_signature`]: #method.set_embedded_signature
+ ///
+ /// This function checks that the [signature type] (passed to
+ /// [`SignatureBuilder::new`], set via
+ /// [`SignatureBuilder::set_type`], or copied when using
+ /// `SignatureBuilder::From`) is [`SignatureType::Timestamp`] or
+ /// [`SignatureType::Unknown`].
+ ///
+ /// [signature type]: ../../types/enum.SignatureType.html
+ /// [`SignatureBuilder::new`]: #method.new
+ /// [`SignatureBuilder::set_type`]: #method.set_type
+ /// [`SignatureType::Timestamp`]: ../../types/enum.SignatureType.html#variant.Timestamp
+ /// [`SignatureType::Unknown`]: ../../types/enum.SignatureType.html#variant.Unknown
+ ///
+ /// The [`Signature`]'s public-key algorithm field is set to the
+ /// algorithm used by `signer`.
+ ///
+ /// [`Signature`]: ../enum.Signature.html
+ ///
+ /// If neither an [`Issuer`] subpacket (set using
+ /// [`SignatureBuilder::set_issuer`], for instance) nor an
+ /// [`Issuer Fingerprint`] subpacket (set using
+ /// [`SignatureBuilder::set_issuer_fingerprint`], for instance) is
+ /// set, they are both added to the new `Signature`'s unhashed
+ /// subpacket area and set to the `signer`'s `KeyID` and
+ /// `Fingerprint`, respectively.
+ ///
+ /// [`Issuer`]: https://tools.ietf.org/html/rfc4880#section-5.2.3.5
+ /// [`SignatureBuilder::set_issuer`]: #method.set_issuer
+ /// [`Issuer Fingerprint`]: https://www.ietf.org/id/draft-ietf-openpgp-rfc4880bis-09.html#section-5.2.3.28
+ /// [`SignatureBuilder::set_issuer_fingerprint`]: #method.set_issuer_fingerprint
+ ///
+ /// Likewise, a [`Signature Creation Time`] subpacket set to the
+ /// current time is added to the hashed area if the `Signature
+ /// Creation Time` subpacket hasn't been set using, for instance,
+ /// the [`set_signature_creation_time`] method or the
+ /// [`preserve_signature_creation_time`] method.
+ ///
+ /// [`Signature Creation Time`]: https://tools.ietf.org/html/rfc4880#section-5.2.3.4
+ /// [`set_signature_creation_time`]: #method.set_signature_creation_time
+ /// [`preserve_signature_creation_time`]: #method.preserve_signature_creation_time
+ ///
+ /// # Examples
+ ///
+ /// Create a timestamp signature:
+ ///
+ /// ```
+ /// use sequoia_openpgp as openpgp;
+ /// use openpgp::cert::prelude::*;
+ /// use openpgp::packet::prelude::*;
+ /// use openpgp::policy::StandardPolicy;
+ /// use openpgp::types::SignatureType;
+ ///
+ /// # fn main() -> openpgp::Result<()> {
+ /// let p = &StandardPolicy::new();
+ ///
+ /// let (cert, _) = CertBuilder::new().add_signing_subkey().generate()?;
+ ///
+ /// // Get a usable (alive, non-revoked) signing key.
+ /// let key : &Key<_, _> = cert
+ /// .keys().with_policy(p, None)
+ /// .for_signing().alive().revoked(false).nth(0).unwrap().key();
+ /// // Derive a signer.
+ /// let mut signer = key.clone().parts_into_secret()?.into_keypair()?;
+ ///
+ /// let sig = SignatureBuilder::new(SignatureType::Timestamp)
+ /// .sign_timestamp(&mut signer)?;
+ ///
+ /// // Verify it.
+ /// sig.verify_timestamp(signer.public())?;
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn sign_timestamp(mut self, signer: &mut dyn Signer)
+ -> Result<Signature>
+ {
+ match self.typ {
+ SignatureType::Timestamp => (),
+ SignatureType::Unknown(_) => (),
+ _ => return Err(Error::UnsupportedSignatureType(self.typ).into()),
+ }
+
+ self = self.pre_sign(signer)?;
+
+ let digest = Signature::hash_timestamp(&self)?;
+
+ self.sign(signer, digest)
+ }
+
+ /// Generates a Direct Key Signature.
+ ///
+ /// A [Direct Key Signature] is a signature over the primary key.
+ /// It is primarily used to hold fallback [preferences]. For
+ /// instance, when addressing the Certificate by a User ID, the
+ /// OpenPGP implementation is supposed to look for preferences
+ /// like the [Preferred Symmetric Algorithms] on the User ID, and
+ /// only if there is no such packet, look on the direct key
+ /// signature.
+ ///
+ /// This function is also used to create a [Key Revocation
+ /// Signature], which revokes the certificate.
+ ///
+ /// [preferences]: ../../cert/trait.Preferences.html
+ /// [Direct Key Signature]: https://tools.ietf.org/html/rfc4880#section-5.2.1
+ /// [Preferred Symmetric Algorithms]: https://tools.ietf.org/html/rfc4880#section-5.2.3.7
+ /// [Key Revocation Signature]: https://tools.ietf.org/html/rfc4880#section-5.2.1
+ ///
+ /// This function checks that the [signature type] (passed to
+ /// [`SignatureBuilder::new`], set via
+ /// [`SignatureBuilder::set_type`], or copied when using
+ /// `SignatureBuilder::From`) is [`SignatureType::DirectKey`],
+ /// [`SignatureType::KeyRevocation`], or
+ /// [`SignatureType::Unknown`].
+ ///
+ /// [signature type]: ../../types/enum.SignatureType.html
+ /// [`SignatureBuilder::new`]: #method.new
+ /// [`SignatureBuilder::set_ty