diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2020-09-30 13:37:28 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2020-10-02 15:09:10 +0200 |
commit | 23cb4b184b8c710d5c54bd45dbad206d59ae36b3 (patch) | |
tree | af1ed73908e82f76faf4817e1383d97b45876622 /openpgp/src/packet/signature.rs | |
parent | b81204994ebd395b0229c0e7eaaa47b7a013ece9 (diff) |
openpgp: Rename file.
Diffstat (limited to 'openpgp/src/packet/signature.rs')
-rw-r--r-- | openpgp/src/packet/signature.rs | 3054 |
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 sig |