sequoia_openpgp/cert.rs
1//! Certificates and related data structures.
2//!
3//! An OpenPGP certificate, often called a `PGP key` or just a `key,`
4//! is a collection of keys, identity information, and certifications
5//! about those keys and identities.
6//!
7//! The foundation of an OpenPGP certificate is the so-called primary
8//! key. A primary key has three essential functions. First, the
9//! primary key is used to derive a universally unique identifier
10//! (UUID) for the certificate, the certificate's so-called
11//! fingerprint. Second, the primary key is used to certify
12//! assertions that the certificate holder makes about their
13//! certificate. For instance, to associate a subkey or a User ID
14//! with a certificate, the certificate holder uses the primary key to
15//! create a self signature called a binding signature. This binding
16//! signature is distributed with the certificate. It allows anyone
17//! who has the certificate to verify that the certificate holder
18//! (identified by the primary key) really intended for the subkey to
19//! be associated with the certificate. Finally, the primary key can
20//! be used to make assertions about other certificates. For
21//! instance, Alice can make a so-called third-party certification
22//! that attests that she is convinced that `Bob` (as described by
23//! some User ID) controls a particular certificate. These
24//! third-party certifications are typically distributed alongside the
25//! signee's certificate, and are used by trust models like the Web of
26//! Trust to authenticate certificates.
27//!
28//! # Common Operations
29//!
30//! - *Generating a certificate*: See the [`CertBuilder`] module.
31//! - *Parsing a certificate*: See the [`Parser` implementation] for `Cert`.
32//! - *Parsing a keyring*: See the [`CertParser`] module.
33//! - *Serializing a certificate*: See the [`Serialize`
34//! implementation] for `Cert`, and the [`Cert::as_tsk`] method to
35//! also include any secret key material.
36//! - *Using a certificate*: See the [`Cert`] and [`ValidCert`] data structures.
37//! - *Revoking a certificate*: See the [`CertRevocationBuilder`] data structure.
38//! - *Decrypt or encrypt secret keys*: See [`packet::Key::encrypt_secret`]'s example.
39//! - *Merging packets*: See the [`Cert::insert_packets`] method.
40//! - *Merging certificates*: See the [`Cert::merge_public`] method.
41//! - *Creating third-party certifications*: See the [`UserID::certify`]
42//! and [`UserAttribute::certify`] methods.
43//! - *Using User IDs and User Attributes*: See the [`ComponentAmalgamation`] module.
44//! - *Using keys*: See the [`KeyAmalgamation`] module.
45//! - *Updating a binding signature*: See the [`UserID::bind`],
46//! [`UserAttribute::bind`], and [`Key::bind`] methods.
47//! - *Checking third-party signatures*: See the
48//! [`Signature::verify_direct_key`],
49//! [`Signature::verify_userid_binding`], and
50//! [`Signature::verify_user_attribute_binding`] methods.
51//! - *Checking third-party revocations*: See the
52//! [`ValidCert::revocation_keys`],
53//! [`ValidAmalgamation::revocation_keys`],
54//! [`Signature::verify_primary_key_revocation`],
55//! [`Signature::verify_userid_revocation`],
56//! [`Signature::verify_user_attribute_revocation`] methods.
57//!
58//! # Data Structures
59//!
60//! ## `Cert`
61//!
62//! The [`Cert`] data structure closely mirrors the transferable
63//! public key (`TPK`) data structure described in [Section 10.1 of
64//! RFC 9580]: it contains the certificate's `Component`s and their
65//! associated signatures.
66//!
67//! ## `Component`s
68//!
69//! In Sequoia, we refer to `User ID`s, `User Attribute`s, and `Key`s
70//! as `Component`s. To accommodate unsupported components (e.g.,
71//! deprecated v3 keys) and unknown components (e.g., the
72//! yet-to-be-defined `Xyzzy Property`), we also define an `Unknown`
73//! component.
74//!
75//! ## `ComponentBundle`s
76//!
77//! We call a Component and any associated signatures a
78//! [`ComponentBundle`]. There are four types of associated
79//! signatures: self signatures, third-party signatures, self
80//! revocations, and third-party revocations.
81//!
82//! Although some information about a given `Component` is stored in
83//! the `Component` itself, most of the information is stored on the
84//! associated signatures. For instance, a key's creation time is
85//! stored in the key packet, but the key's capabilities (e.g.,
86//! whether it can be used for encryption or signing), and its expiry
87//! are stored in the associated self signatures. Thus, to use a
88//! component, we usually need its corresponding self signature.
89//!
90//! When a certificate is parsed, Sequoia ensures that all components
91//! (except the primary key) have at least one valid self signature.
92//! However, when using a component, it is still necessary to find the
93//! right self signature. And, unfortunately, finding the
94//! self signature for the primary `Key` is non-trivial: that's the
95//! primary User ID's self signature. Another complication is that if
96//! the self signature doesn't contain the required information, then
97//! the implementation should look for the information on a direct key
98//! signature. Thus, a `ComponentBundle` doesn't contain all of the
99//! information that is needed to use a component.
100//!
101//! ## `ComponentAmalgamation`s
102//!
103//! To workaround this lack of context, we introduce another data
104//! structure called a [`ComponentAmalgamation`]. A
105//! `ComponentAmalgamation` references a `ComponentBundle` and its
106//! associated `Cert`. Unfortunately, we can't include a reference to
107//! the `Cert` in the `ComponentBundle`, because the `Cert` owns the
108//! `ComponentBundle`, and that would create a self-referential data
109//! structure, which is currently not supported in Rust.
110//!
111//! [Section 10.1 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-10.1
112//! [`ComponentBundle`]: bundle::ComponentBundle
113//! [`ComponentAmalgamation`]: amalgamation::ComponentAmalgamation
114//! [`Parser` implementation]: struct.Cert.html#impl-Parse%3C%27a%2C%20Cert%3E
115//! [`Serialize` implementation]: struct.Cert.html#impl-Serialize
116//! [`UserID::certify`]: crate::packet::UserID::certify()
117//! [`UserAttribute::certify`]: crate::packet::user_attribute::UserAttribute::certify()
118//! [`KeyAmalgamation`]: amalgamation::key
119//! [`UserID::bind`]: crate::packet::UserID::bind()
120//! [`UserAttribute::bind`]: crate::packet::user_attribute::UserAttribute::bind()
121//! [`Key::bind`]: crate::packet::Key::bind()
122//! [`Signature::verify_direct_key`]: crate::packet::Signature::verify_direct_key()
123//! [`Signature::verify_userid_binding`]: crate::packet::Signature::verify_userid_binding()
124//! [`Signature::verify_user_attribute_binding`]: crate::packet::Signature::verify_user_attribute_binding()
125//! [`ValidAmalgamation::revocation_keys`]: amalgamation::ValidAmalgamation::revocation_keys
126//! [`Signature::verify_primary_key_revocation`]: crate::packet::Signature::verify_primary_key_revocation()
127//! [`Signature::verify_userid_revocation`]: crate::packet::Signature::verify_userid_revocation()
128//! [`Signature::verify_user_attribute_revocation`]: crate::packet::Signature::verify_user_attribute_revocation()
129
130use std::collections::btree_map::BTreeMap;
131use std::collections::btree_map::Entry;
132use std::collections::hash_map::DefaultHasher;
133use std::cmp::Ordering;
134use std::convert::TryFrom;
135use std::hash::Hasher;
136use std::mem;
137use std::fmt;
138use std::time;
139
140use buffered_reader::BufferedReader;
141
142use crate::{
143 crypto::{
144 Signer,
145 },
146 Error,
147 Result,
148 SignatureType,
149 packet,
150 packet::Signature,
151 packet::Key,
152 packet::key,
153 packet::Tag,
154 packet::UserID,
155 packet::UserAttribute,
156 packet::Unknown,
157 Packet,
158 PacketPile,
159 seal,
160 KeyID,
161 Fingerprint,
162 KeyHandle,
163 policy::Policy,
164};
165use crate::parse::{Cookie, Parse, PacketParserResult, PacketParser};
166use crate::types::{
167 AEADAlgorithm,
168 CompressionAlgorithm,
169 Features,
170 HashAlgorithm,
171 KeyServerPreferences,
172 ReasonForRevocation,
173 RevocationKey,
174 RevocationStatus,
175 SymmetricAlgorithm,
176};
177
178pub mod amalgamation;
179mod builder;
180mod bindings;
181pub mod bundle;
182use bundle::{
183 ComponentBundles,
184 UserIDBundles,
185 UserAttributeBundles,
186 SubkeyBundles,
187 UnknownBundles,
188};
189mod lazysigs;
190mod parser;
191pub mod raw;
192mod revoke;
193
194pub use self::builder::{CertBuilder, CipherSuite, KeyBuilder, SubkeyBuilder};
195
196pub use parser::{
197 CertParser,
198};
199
200pub(crate) use parser::{
201 CertValidator,
202 CertValidity,
203 KeyringValidator,
204 KeyringValidity,
205};
206
207pub use revoke::{
208 SubkeyRevocationBuilder,
209 CertRevocationBuilder,
210 UserAttributeRevocationBuilder,
211 UserIDRevocationBuilder,
212};
213
214pub mod prelude;
215use prelude::*;
216
217const TRACE : bool = false;
218
219// Helper functions.
220
221/// Compare the creation time of two signatures. Order them so that
222/// the more recent signature is first.
223fn canonical_signature_order(a: Option<time::SystemTime>, b: Option<time::SystemTime>)
224 -> Ordering {
225 // Note: None < Some, so the normal ordering is:
226 //
227 // None, Some(old), Some(new)
228 //
229 // Reversing the ordering puts the signatures without a creation
230 // time at the end, which is where they belong.
231 a.cmp(&b).reverse()
232}
233
234/// Compares two signatures by creation time using the MPIs as tie-breaker.
235///
236/// Useful to sort signatures so that the most recent ones are at the
237/// front.
238fn sig_cmp(a: &Signature, b: &Signature) -> Ordering {
239 match canonical_signature_order(a.signature_creation_time(),
240 b.signature_creation_time()) {
241 Ordering::Equal => a.mpis().cmp(b.mpis()),
242 r => r
243 }
244}
245
246impl fmt::Display for Cert {
247 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
248 write!(f, "{}", self.fingerprint())
249 }
250}
251
252/// Returns the certificate holder's preferences.
253///
254/// OpenPGP provides a mechanism for a certificate holder to transmit
255/// information about communication preferences, and key management to
256/// communication partners in an asynchronous manner. This
257/// information is attached to the certificate itself. Specifically,
258/// the different types of information are stored as signature
259/// subpackets in the User IDs' self signatures, and in the
260/// certificate's direct key signature.
261///
262/// OpenPGP allows the certificate holder to specify different
263/// information depending on the way the certificate is addressed.
264/// When addressed by User ID, that User ID's self signature is first
265/// checked for the subpacket in question. If the subpacket is not
266/// present or the certificate is addressed is some other way, for
267/// instance, by its fingerprint, then the primary User ID's
268/// self signature is checked. If the subpacket is also not there,
269/// then the direct key signature is checked. This policy and its
270/// justification are described in [Section 5.2.3.10 of RFC 9580].
271///
272/// Note: User IDs may be stripped. For instance, the [WKD] standard
273/// requires User IDs that are unrelated to the WKD's domain be
274/// stripped from the certificate prior to publication. As such, any
275/// User ID may be considered the primary User ID. Consequently, if
276/// any User ID includes a particular subpacket, then all User IDs
277/// should include it. Furthermore, [Section 10.1.1 of RFC 9580]
278/// allows certificates without any User ID packets. To handle this
279/// case, certificates should also create a direct key signature with
280/// this information.
281///
282/// [Section 5.2.3.10 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.10
283/// [Section 10.1.1 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-10.1.1
284/// [WKD]: https://tools.ietf.org/html/draft-koch-openpgp-webkey-service-09#section-5
285///
286/// # Algorithm Preferences
287///
288/// Algorithms are ordered with the most preferred algorithm first.
289/// If an algorithm is not listed, then the
290/// implementation should assume that it is not supported by the
291/// certificate holder's software (see e.g. [Section 5.2.3.15 of RFC
292/// 9580]).
293///
294/// [Section 5.2.3.15 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.15
295///
296/// # Examples
297///
298/// ```
299/// use sequoia_openpgp as openpgp;
300/// # use openpgp::Result;
301/// use openpgp::cert::prelude::*;
302/// use sequoia_openpgp::policy::StandardPolicy;
303///
304/// # fn main() -> Result<()> {
305/// let p = &StandardPolicy::new();
306///
307/// # let (cert, _) =
308/// # CertBuilder::general_purpose(Some("alice@example.org"))
309/// # .generate()?;
310/// match cert.with_policy(p, None)?.primary_userid()?.preferred_symmetric_algorithms() {
311/// Some(algos) => {
312/// println!("Certificate Holder's preferred symmetric algorithms:");
313/// for (i, algo) in algos.iter().enumerate() {
314/// println!("{}. {}", i, algo);
315/// }
316/// }
317/// None => {
318/// println!("Certificate Holder did not specify any preferred \
319/// symmetric algorithms, or the subpacket is missing.");
320/// }
321/// }
322/// # Ok(()) }
323/// ```
324///
325/// # Sealed trait
326///
327/// This trait is [sealed] and cannot be implemented for types outside this crate.
328/// Therefore it can be extended in a non-breaking way.
329/// If you want to implement the trait inside the crate
330/// you also need to implement the `seal::Sealed` marker trait.
331///
332/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
333pub trait Preferences<'a>: seal::Sealed {
334 /// Returns the supported symmetric algorithms ordered by
335 /// preference.
336 ///
337 /// The algorithms are ordered according to the certificate
338 /// holder's preference.
339 fn preferred_symmetric_algorithms(&self)
340 -> Option<&'a [SymmetricAlgorithm]>;
341
342 /// Returns the supported hash algorithms ordered by preference.
343 ///
344 /// The algorithms are ordered according to the certificate
345 /// holder's preference.
346 fn preferred_hash_algorithms(&self) -> Option<&'a [HashAlgorithm]>;
347
348 /// Returns the supported compression algorithms ordered by
349 /// preference.
350 ///
351 /// The algorithms are ordered according to the certificate
352 /// holder's preference.
353 fn preferred_compression_algorithms(&self)
354 -> Option<&'a [CompressionAlgorithm]>;
355
356 /// Returns the supported AEAD ciphersuites ordered by preference.
357 ///
358 /// The algorithms are ordered according to the certificate holder's
359 /// preference.
360 fn preferred_aead_ciphersuites(
361 &self)
362 -> Option<&'a [(SymmetricAlgorithm, AEADAlgorithm)]>;
363
364 /// Returns the certificate holder's keyserver preferences.
365 fn key_server_preferences(&self) -> Option<KeyServerPreferences>;
366
367 /// Returns the certificate holder's preferred keyserver for
368 /// updates.
369 fn preferred_key_server(&self) -> Option<&'a [u8]>;
370
371 /// Returns the certificate holder's feature set.
372 fn features(&self) -> Option<Features>;
373
374 /// Returns the URI of a document describing the policy
375 /// the certificate was issued under.
376 fn policy_uri(&self) -> Option<&'a [u8]>;
377}
378
379/// A collection of components and their associated signatures.
380///
381/// The `Cert` data structure mirrors the [TPK and TSK data
382/// structures] defined in RFC 9580. Specifically, it contains
383/// components ([`Key`]s, [`UserID`]s, and [`UserAttribute`]s), their
384/// associated self signatures, self revocations, third-party
385/// signatures, and third-party revocations, as well as useful methods.
386///
387/// [TPK and TSK data structures]: https://www.rfc-editor.org/rfc/rfc9580.html#section-10
388/// [`Key`]: crate::packet::Key
389/// [`UserID`]: crate::packet::UserID
390/// [`UserAttribute`]: crate::packet::user_attribute::UserAttribute
391///
392/// `Cert`s are canonicalized in the sense that their `Component`s are
393/// deduplicated, and their signatures and revocations are
394/// deduplicated and checked for validity. The canonicalization
395/// routine does *not* throw away components that have no self
396/// signatures. These are returned as usual by, e.g.,
397/// [`Cert::userids`].
398///
399/// [`Cert::userids`]: Cert::userids()
400///
401/// Keys are deduplicated by comparing their public bits using
402/// [`Key::public_cmp`]. If two keys are considered equal, and only
403/// one of them has secret key material, the key with the secret key
404/// material is preferred. If both keys have secret material, then
405/// one of them is chosen in a deterministic, but undefined manner,
406/// which is subject to change. ***Note***: the secret key material
407/// is not integrity checked. Hence when updating a certificate with
408/// secret key material, it is essential to first strip the secret key
409/// material from copies that came from an untrusted source.
410///
411/// [`Key::public_cmp`]: crate::packet::Key::public_cmp()
412///
413/// Signatures are deduplicated using [their `Eq` implementation],
414/// which compares the data that is hashed and the MPIs. That is, it
415/// does not compare [the unhashed data], the digest prefix and the
416/// unhashed subpacket area. If two signatures are considered equal,
417/// but have different unhashed data, the unhashed data are merged in
418/// a deterministic, but undefined manner, which is subject to change.
419/// This policy prevents an attacker from flooding a certificate with
420/// valid signatures that only differ in their unhashed data.
421///
422/// [their `Eq` implementation]: crate::packet::Signature#a-note-on-equality
423/// [the unhashed data]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3
424///
425/// Self signatures and self revocations are checked for validity by
426/// making sure that the signature is *mathematically* correct. At
427/// this point, the signature is *not* checked against a [`Policy`].
428///
429/// Third-party signatures and revocations are checked for validity by
430/// making sure the computed digest matches the [digest prefix] stored
431/// in the signature packet. This is *not* an integrity check and is
432/// easily spoofed. Unfortunately, at the time of canonicalization,
433/// the actual signatures cannot be checked, because the public keys
434/// are not available. If you rely on these signatures, it is up to
435/// you to check their validity by using an appropriate signature
436/// verification method, e.g., [`Signature::verify_userid_binding`]
437/// or [`Signature::verify_userid_revocation`].
438///
439/// [`Policy`]: crate::policy::Policy
440/// [digest prefix]: crate::packet::signature::Signature4::digest_prefix()
441/// [`Signature::verify_userid_binding`]: crate::packet::Signature::verify_userid_binding()
442/// [`Signature::verify_userid_revocation`]: crate::packet::Signature::verify_userid_revocation()
443///
444/// If a signature or a revocation is not valid,
445/// we check to see whether it is simply out of place (i.e., belongs
446/// to a different component) and, if so, we reorder it. If not, it
447/// is added to a list of bad signatures. These can be retrieved
448/// using [`Cert::bad_signatures`].
449///
450/// [`Cert::bad_signatures`]: Cert::bad_signatures()
451///
452/// Signatures and revocations are sorted so that the newest signature
453/// comes first. Components are sorted, but in an undefined manner
454/// (i.e., when parsing the same certificate multiple times, the
455/// components will be in the same order, but we reserve the right to
456/// change the sort function between versions).
457///
458/// # Secret Keys
459///
460/// Any key in a certificate may include secret key material. To
461/// protect secret key material from being leaked, secret keys are not
462/// written out when a `Cert` is serialized. To also serialize secret
463/// key material, you need to serialize the object returned by
464/// [`Cert::as_tsk()`].
465///
466///
467/// Secret key material may be protected with a password. In such
468/// cases, it needs to be decrypted before it can be used to decrypt
469/// data or generate a signature. Refer to [`Key::decrypt_secret`]
470/// for details.
471///
472/// [`Key::decrypt_secret`]: crate::packet::Key::decrypt_secret()
473///
474/// # Filtering Certificates
475///
476/// Component-wise filtering of userids, user attributes, and subkeys
477/// can be done with [`Cert::retain_userids`],
478/// [`Cert::retain_user_attributes`], and [`Cert::retain_subkeys`].
479///
480/// [`Cert::retain_userids`]: Cert::retain_userids()
481/// [`Cert::retain_user_attributes`]: Cert::retain_user_attributes()
482/// [`Cert::retain_subkeys`]: Cert::retain_subkeys()
483///
484/// If you need even more control, iterate over all components, clone
485/// what you want to keep, and then reassemble the certificate. The
486/// following example simply copies all the packets, and can be
487/// adapted to suit your policy:
488///
489/// ```rust
490/// # use sequoia_openpgp as openpgp;
491/// # use openpgp::Result;
492/// # use openpgp::parse::{Parse, PacketParserResult, PacketParser};
493/// use std::convert::TryFrom;
494/// use openpgp::cert::prelude::*;
495///
496/// # fn main() -> Result<()> {
497/// fn identity_filter(cert: &Cert) -> Result<Cert> {
498/// // Iterate over all the Cert components, pushing packets we
499/// // want to keep into the accumulator.
500/// let mut acc = Vec::new();
501///
502/// // Primary key and related signatures.
503/// let c = cert.primary_key();
504/// acc.push(c.key().clone().into());
505/// for s in c.self_signatures() { acc.push(s.clone().into()) }
506/// for s in c.certifications() { acc.push(s.clone().into()) }
507/// for s in c.self_revocations() { acc.push(s.clone().into()) }
508/// for s in c.other_revocations() { acc.push(s.clone().into()) }
509///
510/// // UserIDs and related signatures.
511/// for c in cert.userids() {
512/// acc.push(c.userid().clone().into());
513/// for s in c.self_signatures() { acc.push(s.clone().into()) }
514/// for s in c.approvals() { acc.push(s.clone().into()) }
515/// for s in c.certifications() { acc.push(s.clone().into()) }
516/// for s in c.self_revocations() { acc.push(s.clone().into()) }
517/// for s in c.other_revocations() { acc.push(s.clone().into()) }
518/// }
519///
520/// // UserAttributes and related signatures.
521/// for c in cert.user_attributes() {
522/// acc.push(c.user_attribute().clone().into());
523/// for s in c.self_signatures() { acc.push(s.clone().into()) }
524/// for s in c.approvals() { acc.push(s.clone().into()) }
525/// for s in c.certifications() { acc.push(s.clone().into()) }
526/// for s in c.self_revocations() { acc.push(s.clone().into()) }
527/// for s in c.other_revocations() { acc.push(s.clone().into()) }
528/// }
529///
530/// // Subkeys and related signatures.
531/// for c in cert.keys().subkeys() {
532/// acc.push(c.key().clone().into());
533/// for s in c.self_signatures() { acc.push(s.clone().into()) }
534/// for s in c.certifications() { acc.push(s.clone().into()) }
535/// for s in c.self_revocations() { acc.push(s.clone().into()) }
536/// for s in c.other_revocations() { acc.push(s.clone().into()) }
537/// }
538///
539/// // Unknown components and related signatures.
540/// for c in cert.unknowns() {
541/// acc.push(c.unknown().clone().into());
542/// for s in c.self_signatures() { acc.push(s.clone().into()) }
543/// for s in c.certifications() { acc.push(s.clone().into()) }
544/// for s in c.self_revocations() { acc.push(s.clone().into()) }
545/// for s in c.other_revocations() { acc.push(s.clone().into()) }
546/// }
547///
548/// // Any signatures that we could not associate with a component.
549/// for s in cert.bad_signatures() { acc.push(s.clone().into()) }
550///
551/// // Finally, parse into Cert.
552/// Cert::try_from(acc)
553/// }
554///
555/// let (cert, _) =
556/// CertBuilder::general_purpose(Some("alice@example.org"))
557/// .generate()?;
558/// assert_eq!(cert, identity_filter(&cert)?);
559/// # Ok(())
560/// # }
561/// ```
562///
563/// # A note on equality
564///
565/// We define equality on `Cert` as the equality of the serialized
566/// form as defined by RFC 9580. That is, two certs are considered
567/// equal if and only if their serialized forms are equal, modulo the
568/// OpenPGP packet framing (see [`Packet`#a-note-on-equality]).
569///
570/// Because secret key material is not emitted when a `Cert` is
571/// serialized, two certs are considered equal even if only one of
572/// them has secret key material. To take secret key material into
573/// account, compare the [`TSK`s](crate::serialize::TSK) instead:
574///
575/// ```rust
576/// # fn main() -> sequoia_openpgp::Result<()> {
577/// # use sequoia_openpgp as openpgp;
578/// use openpgp::cert::prelude::*;
579///
580/// // Generate a cert with secrets.
581/// let (cert_with_secrets, _) =
582/// CertBuilder::general_purpose(Some("alice@example.org"))
583/// .generate()?;
584///
585/// // Derive a cert without secrets.
586/// let cert_without_secrets =
587/// cert_with_secrets.clone().strip_secret_key_material();
588///
589/// // Both are considered equal.
590/// assert!(cert_with_secrets == cert_without_secrets);
591///
592/// // But not if we compare their TSKs:
593/// assert!(cert_with_secrets.as_tsk() != cert_without_secrets.as_tsk());
594/// # Ok(()) }
595/// ```
596///
597/// # Examples
598///
599/// Parse a certificate:
600///
601/// ```rust
602/// use std::convert::TryFrom;
603/// use sequoia_openpgp as openpgp;
604/// # use openpgp::Result;
605/// # use openpgp::parse::{Parse, PacketParserResult, PacketParser};
606/// use openpgp::Cert;
607///
608/// # fn main() -> Result<()> {
609/// # let ppr = PacketParser::from_bytes(&b""[..])?;
610/// match Cert::try_from(ppr) {
611/// Ok(cert) => {
612/// println!("Key: {}", cert.fingerprint());
613/// for uid in cert.userids() {
614/// println!("User ID: {}", uid.userid());
615/// }
616/// }
617/// Err(err) => {
618/// eprintln!("Error parsing Cert: {}", err);
619/// }
620/// }
621///
622/// # Ok(())
623/// # }
624/// ```
625#[derive(Debug, Clone, PartialEq)]
626pub struct Cert {
627 primary: PrimaryKeyBundle<key::PublicParts>,
628
629 userids: UserIDBundles,
630 user_attributes: UserAttributeBundles,
631 subkeys: SubkeyBundles<key::PublicParts>,
632
633 // Unknown components, e.g., some UserAttribute++ packet from the
634 // future.
635 unknowns: UnknownBundles,
636 // Signatures that we couldn't find a place for.
637 bad: Vec<packet::Signature>,
638}
639assert_send_and_sync!(Cert);
640
641impl std::str::FromStr for Cert {
642 type Err = anyhow::Error;
643
644 /// Parses and returns a certificate.
645 ///
646 /// `s` must return an OpenPGP-encoded certificate.
647 ///
648 /// If `s` contains multiple certificates, this returns an error.
649 /// Use [`CertParser`] if you want to parse a keyring.
650 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
651 Self::from_bytes(s.as_bytes())
652 }
653}
654
655impl<'a> Parse<'a, Cert> for Cert {
656 /// Parses and returns a certificate.
657 ///
658 /// The reader must return an OpenPGP-encoded certificate.
659 ///
660 /// If `reader` contains multiple certificates, this returns an
661 /// error. Use [`CertParser`] if you want to parse a keyring.
662 fn from_buffered_reader<R>(reader: R) -> Result<Cert>
663 where
664 R: BufferedReader<Cookie> + 'a,
665 {
666 Cert::try_from(PacketParser::from_buffered_reader(reader.into_boxed())?)
667 }
668}
669
670impl Cert {
671 /// Returns the primary key.
672 ///
673 /// Unlike getting the certificate's primary key using the
674 /// [`Cert::keys`] method, this method does not erase the key's
675 /// role.
676 ///
677 /// A key's secret key material may be protected with a password.
678 /// In such cases, it needs to be decrypted before it can be used
679 /// to decrypt data or generate a signature. Refer to
680 /// [`Key::decrypt_secret`] for details.
681 ///
682 /// [`Cert::keys`]: Cert::keys()
683 /// [`Key::decrypt_secret`]: crate::packet::Key::decrypt_secret()
684 ///
685 /// # Examples
686 ///
687 /// The first key returned by [`Cert::keys`] is the primary key,
688 /// but its role has been erased:
689 ///
690 /// ```
691 /// # use sequoia_openpgp as openpgp;
692 /// # use openpgp::cert::prelude::*;
693 /// # fn main() -> openpgp::Result<()> {
694 /// # let (cert, _) = CertBuilder::new()
695 /// # .add_userid("Alice")
696 /// # .add_signing_subkey()
697 /// # .add_transport_encryption_subkey()
698 /// # .generate()?;
699 /// assert_eq!(cert.primary_key().key().role_as_unspecified(),
700 /// cert.keys().nth(0).unwrap().key());
701 /// # Ok(())
702 /// # }
703 /// ```
704 pub fn primary_key(&self) -> PrimaryKeyAmalgamation<'_, key::PublicParts>
705 {
706 PrimaryKeyAmalgamation::new(self)
707 }
708
709 /// Returns the certificate's revocation status.
710 ///
711 /// Normally, methods that take a policy and a reference time are
712 /// only provided by [`ValidCert`]. This method is provided here
713 /// because there are two revocation criteria, and one of them is
714 /// independent of the reference time. That is, even if it is not
715 /// possible to turn a `Cert` into a `ValidCert` at time `t`, it
716 /// may still be considered revoked at time `t`.
717 ///
718 ///
719 /// A certificate is considered revoked at time `t` if:
720 ///
721 /// - There is a valid and live revocation at time `t` that is
722 /// newer than all valid and live self signatures at time `t`,
723 /// or
724 ///
725 /// - There is a valid [hard revocation] (even if it is not live
726 /// at time `t`, and even if there is a newer self signature).
727 ///
728 /// [hard revocation]: crate::types::RevocationType::Hard
729 ///
730 /// Note: certificates and subkeys have different revocation
731 /// criteria from [User IDs] and [User Attributes].
732 ///
733 // Pending https://github.com/rust-lang/rust/issues/85960, should be
734 // [User IDs]: bundle::ComponentBundle<UserID>::revocation_status
735 // [User Attributes]: bundle::ComponentBundle<UserAttribute>::revocation_status
736 /// [User IDs]: bundle::ComponentBundle#method.revocation_status-1
737 /// [User Attributes]: bundle::ComponentBundle#method.revocation_status-2
738 ///
739 /// # Examples
740 ///
741 /// ```
742 /// use sequoia_openpgp as openpgp;
743 /// use openpgp::cert::prelude::*;
744 /// use openpgp::types::RevocationStatus;
745 /// use openpgp::policy::StandardPolicy;
746 ///
747 /// # fn main() -> openpgp::Result<()> {
748 /// let p = &StandardPolicy::new();
749 ///
750 /// let (cert, rev) =
751 /// CertBuilder::general_purpose(Some("alice@example.org"))
752 /// .generate()?;
753 ///
754 /// assert_eq!(cert.revocation_status(p, None), RevocationStatus::NotAsFarAsWeKnow);
755 ///
756 /// // Merge the revocation certificate. `cert` is now considered
757 /// // to be revoked.
758 /// let cert = cert.insert_packets(rev.clone())?.0;
759 /// assert_eq!(cert.revocation_status(p, None),
760 /// RevocationStatus::Revoked(vec![&rev.into()]));
761 /// # Ok(())
762 /// # }
763 /// ```
764 pub fn revocation_status<T>(&self, policy: &dyn Policy, t: T) -> RevocationStatus<'_>
765 where T: Into<Option<time::SystemTime>>
766 {
767 let t = t.into();
768 // Both a primary key signature and the primary userid's
769 // binding signature can override a soft revocation. Compute
770 // the most recent one.
771 let vkao = self.primary_key().with_policy(policy, t).ok();
772 let mut sig = vkao.as_ref().map(|vka| vka.binding_signature());
773 if let Some(direct) = vkao.as_ref()
774 .and_then(|vka| vka.direct_key_signature().ok())
775 {
776 match (direct.signature_creation_time(),
777 sig.and_then(|s| s.signature_creation_time())) {
778 (Some(ds), Some(bs)) if ds > bs =>
779 sig = Some(direct),
780 _ => ()
781 }
782 }
783 self.primary_key().bundle().revocation_status_intern(
784 policy, t, true, sig)
785 }
786
787 /// Generates a revocation certificate.
788 ///
789 /// This is a convenience function around
790 /// [`CertRevocationBuilder`] to generate a revocation
791 /// certificate. To use the revocation certificate, merge it into
792 /// the certificate using [`Cert::insert_packets`].
793 ///
794 ///
795 /// If you want to revoke an individual component, use
796 /// [`SubkeyRevocationBuilder`], [`UserIDRevocationBuilder`], or
797 /// [`UserAttributeRevocationBuilder`], as appropriate.
798 ///
799 ///
800 /// # Examples
801 ///
802 /// ```rust
803 /// use sequoia_openpgp as openpgp;
804 /// # use openpgp::Result;
805 /// use openpgp::types::{ReasonForRevocation, RevocationStatus, SignatureType};
806 /// use openpgp::cert::prelude::*;
807 /// use openpgp::crypto::KeyPair;
808 /// use openpgp::parse::Parse;
809 /// use openpgp::policy::StandardPolicy;
810 ///
811 /// # fn main() -> Result<()> {
812 /// let p = &StandardPolicy::new();
813 ///
814 /// let (cert, rev) = CertBuilder::new()
815 /// .set_cipher_suite(CipherSuite::Cv25519)
816 /// .generate()?;
817 ///
818 /// // A new certificate is not revoked.
819 /// assert_eq!(cert.revocation_status(p, None),
820 /// RevocationStatus::NotAsFarAsWeKnow);
821 ///
822 /// // The default revocation certificate is a generic
823 /// // revocation.
824 /// assert_eq!(rev.reason_for_revocation().unwrap().0,
825 /// ReasonForRevocation::Unspecified);
826 ///
827 /// // Create a revocation to explain what *really* happened.
828 /// let mut keypair = cert.primary_key()
829 /// .key().clone().parts_into_secret()?.into_keypair()?;
830 /// let rev = cert.revoke(&mut keypair,
831 /// ReasonForRevocation::KeyCompromised,
832 /// b"It was the maid :/")?;
833 /// let cert = cert.insert_packets(rev)?.0;
834 /// if let RevocationStatus::Revoked(revs) = cert.revocation_status(p, None) {
835 /// assert_eq!(revs.len(), 1);
836 /// let rev = revs[0];
837 ///
838 /// assert_eq!(rev.typ(), SignatureType::KeyRevocation);
839 /// assert_eq!(rev.reason_for_revocation(),
840 /// Some((ReasonForRevocation::KeyCompromised,
841 /// "It was the maid :/".as_bytes())));
842 /// } else {
843 /// unreachable!()
844 /// }
845 /// # Ok(())
846 /// # }
847 /// ```
848 pub fn revoke(&self, primary_signer: &mut dyn Signer,
849 code: ReasonForRevocation, reason: &[u8])
850 -> Result<Signature>
851 {
852 CertRevocationBuilder::new()
853 .set_reason_for_revocation(code, reason)?
854 .build(primary_signer, self, None)
855 }
856
857 /// Sets the key to expire in delta seconds.
858 ///
859 /// Note: the time is relative to the key's creation time, not the
860 /// current time!
861 ///
862 /// This function exists to facilitate testing, which is why it is
863 /// not exported.
864 #[cfg(test)]
865 fn set_validity_period_as_of(self, policy: &dyn Policy,
866 primary_signer: &mut dyn Signer,
867 expiration: Option<time::Duration>,
868 now: time::SystemTime)
869 -> Result<Cert>
870 {
871 let primary = self.primary_key().with_policy(policy, now)?;
872 let sigs = primary.set_validity_period_as_of(primary_signer,
873 expiration,
874 now)?;
875 Ok(self.insert_packets(sigs)?.0)
876 }
877
878 /// Sets the certificate to expire at the specified time.
879 ///
880 /// If no time (`None`) is specified, then the certificate is set
881 /// to not expire.
882 ///
883 /// This function creates new binding signatures that cause the
884 /// certificate to expire at the specified time. Specifically, it
885 /// updates the current binding signature on each of the valid,
886 /// non-revoked User IDs, and the direct key signature, if any.
887 /// This is necessary, because the primary User ID is first
888 /// consulted when determining the certificate's expiration time,
889 /// and certificates can be distributed with a possibly empty
890 /// subset of User IDs.
891 ///
892 /// A policy is needed, because the expiration is updated by
893 /// updating the current binding signatures.
894 ///
895 /// # Examples
896 ///
897 /// ```rust
898 /// use std::time;
899 /// use sequoia_openpgp as openpgp;
900 /// # use openpgp::Result;
901 /// use openpgp::cert::prelude::*;
902 /// use openpgp::crypto::KeyPair;
903 /// use openpgp::policy::StandardPolicy;
904 ///
905 /// # fn main() -> Result<()> {
906 /// let p = &StandardPolicy::new();
907 ///
908 /// # let t0 = time::SystemTime::now() - time::Duration::from_secs(1);
909 /// # let (cert, _) = CertBuilder::new()
910 /// # .set_cipher_suite(CipherSuite::Cv25519)
911 /// # .set_creation_time(t0)
912 /// # .generate()?;
913 /// // The certificate is alive (not expired).
914 /// assert!(cert.with_policy(p, None)?.alive().is_ok());
915 ///
916 /// // Make cert expire now.
917 /// let mut keypair = cert.primary_key()
918 /// .key().clone().parts_into_secret()?.into_keypair()?;
919 /// let sigs = cert.set_expiration_time(p, None, &mut keypair,
920 /// Some(time::SystemTime::now()))?;
921 ///
922 /// let cert = cert.insert_packets(sigs)?.0;
923 /// assert!(cert.with_policy(p, None)?.alive().is_err());
924 /// # Ok(())
925 /// # }
926 /// ```
927 pub fn set_expiration_time<T>(&self, policy: &dyn Policy, t: T,
928 primary_signer: &mut dyn Signer,
929 expiration: Option<time::SystemTime>)
930 -> Result<Vec<Signature>>
931 where T: Into<Option<time::SystemTime>>,
932 {
933 let primary = self.primary_key().with_policy(policy, t.into())?;
934 primary.set_expiration_time(primary_signer, expiration)
935 }
936
937 /// Returns the primary User ID at the reference time, if any.
938 fn primary_userid_relaxed<'a, T>(&'a self, policy: &'a dyn Policy, t: T,
939 valid_cert: bool)
940 -> Result<ValidUserIDAmalgamation<'a>>
941 where T: Into<Option<std::time::SystemTime>>
942 {
943 let t = t.into().unwrap_or_else(crate::now);
944 ValidComponentAmalgamation::primary(self, self.userids.iter(),
945 policy, t, valid_cert)
946 }
947
948 /// Returns an iterator over the certificate's User IDs.
949 ///
950 /// **Note:** This returns all User IDs, even those without a
951 /// binding signature. This is not what you want, unless you are
952 /// doing a low-level inspection of the certificate. Use
953 /// [`ValidCert::userids`] instead. (You turn a `Cert` into a
954 /// [`ValidCert`] by using [`Cert::with_policy`].)
955 ///
956 /// # Examples
957 ///
958 /// ```
959 /// # use sequoia_openpgp as openpgp;
960 /// # use openpgp::cert::prelude::*;
961 /// # use openpgp::packet::prelude::*;
962 /// #
963 /// # fn main() -> openpgp::Result<()> {
964 /// # let (cert, rev) =
965 /// # CertBuilder::general_purpose(Some("alice@example.org"))
966 /// # .generate()?;
967 /// println!("{}'s User IDs:", cert.fingerprint());
968 /// for ua in cert.userids() {
969 /// println!(" {}", String::from_utf8_lossy(ua.userid().value()));
970 /// }
971 /// # // Add a User ID without a binding signature and make sure
972 /// # // it is still returned.
973 /// # let userid = UserID::from("alice@example.net");
974 /// # let cert = cert.insert_packets(userid)?.0;
975 /// # assert_eq!(cert.userids().count(), 2);
976 /// # Ok(())
977 /// # }
978 /// ```
979 pub fn userids(&self) -> UserIDAmalgamationIter<'_> {
980 ComponentAmalgamationIter::new(self, self.userids.iter())
981 }
982
983 /// Returns an iterator over the certificate's User Attributes.
984 ///
985 /// **Note:** This returns all User Attributes, even those without
986 /// a binding signature. This is not what you want, unless you
987 /// are doing a low-level inspection of the certificate. Use
988 /// [`ValidCert::user_attributes`] instead. (You turn a `Cert`
989 /// into a [`ValidCert`] by using [`Cert::with_policy`].)
990 ///
991 /// # Examples
992 ///
993 /// ```
994 /// # use sequoia_openpgp as openpgp;
995 /// # use openpgp::cert::prelude::*;
996 /// #
997 /// # fn main() -> openpgp::Result<()> {
998 /// # let (cert, rev) =
999 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1000 /// # .generate()?;
1001 /// println!("{}'s has {} User Attributes.",
1002 /// cert.fingerprint(),
1003 /// cert.user_attributes().count());
1004 /// # assert_eq!(cert.user_attributes().count(), 0);
1005 /// # Ok(())
1006 /// # }
1007 /// ```
1008 pub fn user_attributes(&self) -> UserAttributeAmalgamationIter<'_> {
1009 ComponentAmalgamationIter::new(self, self.user_attributes.iter())
1010 }
1011
1012 /// Returns an iterator over the certificate's keys.
1013 ///
1014 /// That is, this returns an iterator over the primary key and any
1015 /// subkeys.
1016 ///
1017 /// **Note:** This returns all keys, even those without a binding
1018 /// signature. This is not what you want, unless you are doing a
1019 /// low-level inspection of the certificate. Use
1020 /// [`ValidCert::keys`] instead. (You turn a `Cert` into a
1021 /// [`ValidCert`] by using [`Cert::with_policy`].)
1022 ///
1023 /// By necessity, this function erases the returned keys' roles.
1024 /// If you are only interested in the primary key, use
1025 /// [`Cert::primary_key`]. If you are only interested in the
1026 /// subkeys, use [`KeyAmalgamationIter::subkeys`]. These
1027 /// functions preserve the keys' role in the type system.
1028 ///
1029 /// A key's secret key material may be protected with a
1030 /// password. In such cases, it needs to be decrypted before it
1031 /// can be used to decrypt data or generate a signature. Refer to
1032 /// [`Key::decrypt_secret`] for details.
1033 ///
1034 /// [`Cert::primary_key`]: Cert::primary_key()
1035 /// [`KeyAmalgamationIter::subkeys`]: amalgamation::key::KeyAmalgamationIter::subkeys()
1036 /// [`Key::decrypt_secret`]: crate::packet::Key::decrypt_secret()
1037 ///
1038 /// # Examples
1039 ///
1040 /// ```
1041 /// # use sequoia_openpgp as openpgp;
1042 /// # use openpgp::cert::prelude::*;
1043 /// # use openpgp::packet::Tag;
1044 /// # use std::convert::TryInto;
1045 /// #
1046 /// # fn main() -> openpgp::Result<()> {
1047 /// # let (cert, _) = CertBuilder::new()
1048 /// # .add_userid("Alice")
1049 /// # .add_signing_subkey()
1050 /// # .add_transport_encryption_subkey()
1051 /// # .generate()?;
1052 /// println!("{}'s has {} keys.",
1053 /// cert.fingerprint(),
1054 /// cert.keys().count());
1055 /// # assert_eq!(cert.keys().count(), 1 + 2);
1056 /// #
1057 /// # // Make sure that we keep all keys even if they don't have
1058 /// # // any self signatures.
1059 /// # let packets = cert.into_packets()
1060 /// # .filter(|p| p.tag() != Tag::Signature)
1061 /// # .collect::<Vec<_>>();
1062 /// # let cert : Cert = packets.try_into()?;
1063 /// # assert_eq!(cert.keys().count(), 1 + 2);
1064 /// #
1065 /// # Ok(())
1066 /// # }
1067 /// ```
1068 pub fn keys(&self) -> KeyAmalgamationIter<'_, key::PublicParts, key::UnspecifiedRole>
1069 {
1070 KeyAmalgamationIter::new(self)
1071 }
1072
1073 /// Returns an iterator over the certificate's subkeys.
1074 ///
1075 /// This is used in many test. But, its convenience and
1076 /// availability made us use it here and there in the code.
1077 /// Nowadays, we use it in tests, and it is merely an alias for
1078 /// the public interface. Do not use it for new tests.
1079 #[cfg(test)]
1080 pub(crate) fn subkeys(&self)
1081 -> KeyAmalgamationIter<'_, key::PublicParts, key::SubordinateRole>
1082 {
1083 self.keys().subkeys()
1084 }
1085
1086 /// Returns an iterator over the certificate's unknown components.
1087 ///
1088 /// This function returns all unknown components even those
1089 /// without a binding signature.
1090 ///
1091 /// # Examples
1092 ///
1093 /// ```
1094 /// # use sequoia_openpgp as openpgp;
1095 /// # use openpgp::packet::prelude::*;
1096 /// # use openpgp::cert::prelude::*;
1097 /// #
1098 /// # fn main() -> openpgp::Result<()> {
1099 /// # let (cert, _) =
1100 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1101 /// # .generate()?;
1102 /// # let tag = Tag::Private(61);
1103 /// # let unknown
1104 /// # = Unknown::new(tag, openpgp::Error::UnsupportedPacketType(tag).into());
1105 /// # let cert = cert.insert_packets(unknown)?.0;
1106 /// println!("{}'s has {} unknown components.",
1107 /// cert.fingerprint(),
1108 /// cert.unknowns().count());
1109 /// for ua in cert.unknowns() {
1110 /// println!(" Unknown component with tag {} ({}), error: {}",
1111 /// ua.unknown().tag(), u8::from(ua.unknown().tag()), ua.unknown().error());
1112 /// }
1113 /// # assert_eq!(cert.unknowns().count(), 1);
1114 /// # assert_eq!(cert.unknowns().nth(0).unwrap().unknown().tag(), tag);
1115 /// # Ok(())
1116 /// # }
1117 /// ```
1118 pub fn unknowns(&self) -> UnknownComponentAmalgamationIter<'_> {
1119 ComponentAmalgamationIter::new(self, self.unknowns.iter())
1120 }
1121
1122 /// Returns the bad signatures.
1123 ///
1124 /// Bad signatures are signatures and revocations that we could
1125 /// not associate with one of the certificate's components.
1126 ///
1127 /// For self signatures and self revocations, we check that the
1128 /// signature is correct. For third-party signatures and
1129 /// third-party revocations, we only check that the [digest
1130 /// prefix] is correct, because third-party keys are not
1131 /// available. Checking the digest prefix is *not* an integrity
1132 /// check; third party-signatures and third-party revocations may
1133 /// be invalid and must still be checked for validity before use.
1134 ///
1135 /// [digest prefix]: packet::signature::Signature4::digest_prefix()
1136 ///
1137 /// # Examples
1138 ///
1139 /// ```
1140 /// # use sequoia_openpgp as openpgp;
1141 /// # use openpgp::cert::prelude::*;
1142 /// #
1143 /// # fn main() -> openpgp::Result<()> {
1144 /// # let (cert, rev) =
1145 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1146 /// # .generate()?;
1147 /// println!("{}'s has {} bad signatures.",
1148 /// cert.fingerprint(),
1149 /// cert.bad_signatures().count());
1150 /// # assert_eq!(cert.bad_signatures().count(), 0);
1151 /// # Ok(())
1152 /// # }
1153 /// ```
1154 pub fn bad_signatures(&self)
1155 -> impl Iterator<Item = &Signature> + Send + Sync {
1156 self.primary.bad_signatures()
1157 .chain(self.userids.iter().flat_map(|u| u.bad_signatures()))
1158 .chain(self.user_attributes.iter().flat_map(|u| u.bad_signatures()))
1159 .chain(self.subkeys.iter().flat_map(|u| u.bad_signatures()))
1160 .chain(self.unknowns.iter().flat_map(|u| u.bad_signatures()))
1161 .chain(self.bad.iter())
1162 }
1163
1164 /// Returns a list of any designated revokers for this certificate.
1165 ///
1166 /// This function returns the designated revokers listed on the
1167 /// primary key's binding signatures and the certificate's direct
1168 /// key signatures.
1169 ///
1170 /// Note: the returned list is deduplicated.
1171 ///
1172 /// # Examples
1173 ///
1174 /// ```
1175 /// use sequoia_openpgp as openpgp;
1176 /// # use openpgp::Result;
1177 /// use openpgp::cert::prelude::*;
1178 /// use openpgp::policy::StandardPolicy;
1179 /// use openpgp::types::RevocationKey;
1180 ///
1181 /// # fn main() -> Result<()> {
1182 /// let p = &StandardPolicy::new();
1183 ///
1184 /// let (alice, _) =
1185 /// CertBuilder::general_purpose(Some("alice@example.org"))
1186 /// .generate()?;
1187 /// // Make Alice a designated revoker for Bob.
1188 /// let (bob, _) =
1189 /// CertBuilder::general_purpose(Some("bob@example.org"))
1190 /// .set_revocation_keys(vec![(&alice).into()])
1191 /// .generate()?;
1192 ///
1193 /// // Make sure Alice is listed as a designated revoker for Bob.
1194 /// assert_eq!(bob.revocation_keys(p).collect::<Vec<&RevocationKey>>(),
1195 /// vec![&(&alice).into()]);
1196 /// # Ok(()) }
1197 /// ```
1198 pub fn revocation_keys<'a>(&'a self, policy: &dyn Policy)
1199 -> impl Iterator<Item = &'a RevocationKey> + 'a
1200 {
1201 let mut keys = std::collections::HashSet::new();
1202
1203 let pk_sec = self.primary_key().key().hash_algo_security();
1204
1205 // All user ids.
1206 self.userids()
1207 .flat_map(|ua| {
1208 // All valid self-signatures.
1209 let sec = ua.userid().hash_algo_security();
1210 ua.self_signatures()
1211 .filter(move |sig| {
1212 policy.signature(sig, sec).is_ok()
1213 })
1214 })
1215 // All direct-key signatures.
1216 .chain(self.primary_key()
1217 .self_signatures()
1218 .filter(|sig| {
1219 policy.signature(sig, pk_sec).is_ok()
1220 }))
1221 .flat_map(|sig| sig.revocation_keys())
1222 .for_each(|rk| { keys.insert(rk); });
1223
1224 keys.into_iter()
1225 }
1226
1227 /// Converts the certificate into an iterator over a sequence of
1228 /// packets.
1229 ///
1230 /// This function strips secrets from the keys, similar to how
1231 /// serializing a [`Cert`] would not serialize secret keys. This
1232 /// behavior makes it harder to accidentally leak secret key
1233 /// material.
1234 ///
1235 /// If you do want to preserve secret key material, use
1236 /// [`Cert::into_tsk`] to opt in to getting the secret key
1237 /// material, then use [`TSK::into_packets`] to convert to a
1238 /// packet stream.
1239 ///
1240 /// # Examples
1241 ///
1242 /// ```
1243 /// # use sequoia_openpgp as openpgp;
1244 /// # use openpgp::cert::prelude::*;
1245 /// #
1246 /// # fn main() -> openpgp::Result<()> {
1247 /// # let (cert, _) =
1248 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1249 /// # .generate()?;
1250 /// assert!(cert.is_tsk());
1251 /// // But:
1252 /// assert!(! Cert::from_packets(cert.into_packets())?.is_tsk());
1253 /// # Ok(()) }
1254 /// ```
1255 pub fn into_packets(self) -> impl Iterator<Item=Packet> + Send + Sync {
1256 /// Strips the secret key material.
1257 fn rewrite(mut p: impl Iterator<Item=Packet> + Send + Sync)
1258 -> impl Iterator<Item=Packet> + Send + Sync
1259 {
1260 let k: Packet = match p.next().unwrap() {
1261 Packet::PublicKey(k) =>
1262 Packet::PublicKey(k.take_secret().0),
1263 Packet::PublicSubkey(k) =>
1264 Packet::PublicSubkey(k.take_secret().0),
1265 _ => unreachable!(),
1266 };
1267
1268 std::iter::once(k).chain(p)
1269 }
1270
1271 rewrite(self.primary.into_packets())
1272 .chain(self.userids.into_iter().flat_map(|b| b.into_packets()))
1273 .chain(self.user_attributes.into_iter().flat_map(|b| b.into_packets()))
1274 .chain(self.subkeys.into_iter().flat_map(|b| rewrite(b.into_packets())))
1275 .chain(self.unknowns.into_iter().flat_map(|b| b.into_packets()))
1276 .chain(self.bad.into_iter().map(|s| s.into()))
1277 }
1278
1279 /// Returns the first certificate found in the sequence of packets.
1280 ///
1281 /// If the sequence of packets does not start with a certificate
1282 /// (specifically, if it does not start with a primary key
1283 /// packet), then this fails.
1284 ///
1285 /// If the sequence contains multiple certificates (i.e., it is a
1286 /// keyring), or the certificate is followed by an invalid packet
1287 /// this function will fail. To parse keyrings, use
1288 /// [`CertParser`] instead of this function.
1289 ///
1290 /// # Examples
1291 ///
1292 /// ```
1293 /// use sequoia_openpgp as openpgp;
1294 /// use openpgp::cert::prelude::*;
1295 /// use openpgp::packet::prelude::*;
1296 /// use openpgp::PacketPile;
1297 ///
1298 /// # fn main() -> openpgp::Result<()> {
1299 /// let (cert, rev) =
1300 /// CertBuilder::general_purpose(Some("alice@example.org"))
1301 /// .generate()?;
1302 ///
1303 /// // We should be able to turn a certificate into a PacketPile
1304 /// // and back.
1305 /// assert!(Cert::from_packets(cert.into_packets()).is_ok());
1306 ///
1307 /// // But a revocation certificate is not a certificate, so this
1308 /// // will fail.
1309 /// let p : Vec<Packet> = vec![rev.into()];
1310 /// assert!(Cert::from_packets(p.into_iter()).is_err());
1311 /// # Ok(())
1312 /// # }
1313 /// ```
1314 pub fn from_packets(p: impl Iterator<Item=Packet> + Send + Sync) -> Result<Self> {
1315 let mut i = parser::CertParser::from_iter(p);
1316 if let Some(cert_result) = i.next() {
1317 if i.next().is_some() {
1318 Err(Error::MalformedCert(
1319 "Additional packets found, is this a keyring?".into()
1320 ).into())
1321 } else {
1322 cert_result
1323 }
1324 } else {
1325 Err(Error::MalformedCert("No data".into()).into())
1326 }
1327 }
1328
1329 /// Converts the certificate into a `PacketPile`.
1330 ///
1331 /// # Examples
1332 ///
1333 /// ```
1334 /// # use sequoia_openpgp as openpgp;
1335 /// # use openpgp::PacketPile;
1336 /// # use openpgp::cert::prelude::*;
1337 /// #
1338 /// # fn main() -> openpgp::Result<()> {
1339 /// # let (cert, _) =
1340 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1341 /// # .generate()?;
1342 /// let pp = cert.into_packet_pile();
1343 /// # let _ : PacketPile = pp;
1344 /// # Ok(())
1345 /// # }
1346 /// ```
1347 pub fn into_packet_pile(self) -> PacketPile {
1348 self.into()
1349 }
1350
1351 /// Sorts and deduplicates all components and all signatures of
1352 /// all components.
1353 ///
1354 /// Signatures are compared using [`Signature::normalized_eq`]
1355 /// (i.e., the unhashed subpacket area is ignored). If two
1356 /// signatures are considered equal, the one that comes first is
1357 /// kept.
1358 ///
1359 /// Keys are compares using [`Key::public_cmp`]. If two keys are
1360 /// considered equivalent, then the one with secret key material
1361 /// is kept. If they both have secret key material, then the one
1362 /// that comes first is kept.
1363 fn sort_and_dedup(&mut self) {
1364 self.primary.sort_and_dedup();
1365
1366 self.bad.sort_by(Signature::normalized_cmp);
1367 self.bad.dedup_by(|a, b| a.normalized_eq(b));
1368 // Order bad signatures so that the most recent one comes
1369 // first.
1370 self.bad.sort_by(sig_cmp);
1371
1372 self.userids.sort_and_dedup(UserID::cmp, |_, _| {});
1373 self.user_attributes.sort_and_dedup(UserAttribute::cmp, |_, _| {});
1374 // XXX: If we have two keys with the same public parts and
1375 // different non-empty secret parts, then the one that comes
1376 // first will be dropped, the one that comes later will be
1377 // kept.
1378 //
1379 // This can happen if:
1380 //
1381 // - One is corrupted
1382 // - There are two versions that are encrypted differently
1383 //
1384 // If the order of the keys is unpredictable, this effect is
1385 // unpredictable! However, if we merge two canonicalized
1386 // certs with Cert::merge_public_and_secret, then we know the
1387 // order: the version in `self` comes first, the version in
1388 // `other` comes last.
1389 self.subkeys.sort_and_dedup(Key::public_cmp,
1390 |a, b| {
1391 // Recall: if a and b are equal, a will be dropped.
1392 // Also, the elements are given in the opposite order
1393 // from their order in the vector.
1394 //
1395 // Prefer the secret in `a`, i.e. the "later" one.
1396 if a.has_secret() {
1397 std::mem::swap(a, b);
1398 }
1399 });
1400
1401 self.unknowns.sort_and_dedup(Unknown::best_effort_cmp, |_, _| {});
1402 }
1403
1404 fn canonicalize(mut self) -> Self {
1405 tracer!(TRACE, "canonicalize", 0);
1406 t!("Canonicalizing {}", self.primary_key().key().fingerprint());
1407 use SignatureType::*;
1408
1409 // Before we do anything, we'll order and deduplicate the
1410 // components. If two components are the same, they will be
1411 // merged, and their signatures will also be deduplicated.
1412 // This improves the performance considerably when we update a
1413 // certificate, because the certificates will be most likely
1414 // almost identical, and we avoid about half of the signature
1415 // verifications.
1416 self.sort_and_dedup();
1417
1418 // Now we verify the self signatures. There are a few things
1419 // that we need to be aware of:
1420 //
1421 // - Signatures may be invalid. These should be dropped.
1422 //
1423 // - Signatures may be out of order. These should be
1424 // reordered so that we have the latest self signature and
1425 // we don't drop a userid or subkey that is actually
1426 // valid.
1427
1428 // We collect bad signatures here in self.bad. Below, we'll
1429 // test whether they are just out of order by checking them
1430 // against all userids and subkeys. Furthermore, this may be
1431 // a partial Cert that is merged into an older copy.
1432
1433 // desc: a description of the component
1434 // binding: the binding to check
1435 // sigs: a vector of sigs in $binding to check
1436 macro_rules! check {
1437 ($desc:expr, $binding:expr, $sigs:ident,
1438 $hash_method:ident, // method to hash the signature
1439 $sig_type_pat:pat, // pattern to test signature types against
1440 $($hash_args:expr),* // additional arguments to pass to hash_method
1441 ) => ({
1442 let sigs = $binding.$sigs.take();
1443 t!("check!({}, {}, {} ({:?}), {}, ...)",
1444 $desc, stringify!($binding), stringify!($sigs), sigs,
1445 stringify!($hash_method));
1446 for sig in sigs.into_iter() {
1447 // Use hash prefix as heuristic.
1448 let key = self.primary.key();
1449 match sig.hash_algo().context().and_then(|ctx| {
1450 let mut ctx = ctx.for_signature(sig.version());
1451 if matches!(sig.typ(), $sig_type_pat) {
1452 sig.$hash_method(&mut ctx, key, $($hash_args),*)?;
1453 ctx.into_digest()
1454 } else {
1455 Err(Error::UnsupportedSignatureType(sig.typ()).into())
1456 }
1457 }) {
1458 Ok(hash) => {
1459 if &sig.digest_prefix()[..] == &hash[..2] {
1460 sig.set_computed_digest(Some(hash));
1461 $binding.$sigs.push(sig);
1462 } else {
1463 t!("Sig {:02X}{:02X}, type = {} \
1464 doesn't belong to {} (computed hash's prefix: {:02X}{:02X})",
1465 sig.digest_prefix()[0], sig.digest_prefix()[1],
1466 sig.typ(), $desc,
1467 hash[0], hash[1]);
1468
1469 self.bad.push(sig);
1470 }
1471 },
1472 Err(e) => {
1473 // Hashing failed, we likely don't support the
1474 // hash algorithm, or the signature type was
1475 // bad.
1476 t!("Sig {:02X}{:02X}, type = {}: {}",
1477 sig.digest_prefix()[0], sig.digest_prefix()[1],
1478 sig.typ(), e);
1479
1480 self.bad.push(sig);
1481 },
1482 }
1483 }
1484 });
1485 ($desc:expr, $binding:expr, $sigs:ident,
1486 $hash_method:ident, $sig_type_pat:pat) => ({
1487 check!($desc, $binding, $sigs, $hash_method, $sig_type_pat, )
1488 });
1489 }
1490
1491 // The same as check!, but for third party signatures. If we
1492 // do have the key that made the signature, we can verify it
1493 // like in check!. Otherwise, we use the hash prefix as
1494 // heuristic approximating the verification.
1495 macro_rules! check_3rd_party {
1496 ($desc:expr, // a description of the component
1497 $binding:expr, // the binding to check
1498 $sigs:ident, // a vector of sigs in $binding to check
1499 $lookup_fn:expr, // a function to lookup keys
1500 $verify_method:ident, // the method to call to verify it
1501 $hash_method:ident, // the method to call to compute the hash
1502 $sig_type_pat:pat, // pattern to test signature types against
1503 $($verify_args:expr),* // additional arguments to pass to the above
1504 ) => ({
1505 let sigs = mem::take(&mut $binding.$sigs);
1506 t!("check_3rd_party!({}, {}, {} ({:?}_, {}, {}, ...)",
1507 $desc, stringify!($binding), stringify!($sigs), sigs,
1508 stringify!($verify_method), stringify!($hash_method));
1509 for sig in sigs {
1510 // Use hash prefix as heuristic.
1511 let key = self.primary.key();
1512 match sig.hash_algo().context().and_then(|ctx| {
1513 let mut ctx = ctx.for_signature(sig.version());
1514 if matches!(sig.typ(), $sig_type_pat) {
1515 sig.$hash_method(&mut ctx, key, $($verify_args),*)?;
1516 ctx.into_digest()
1517 } else {
1518 Err(Error::UnsupportedSignatureType(sig.typ()).into())
1519 }
1520 }) {
1521 Ok(hash) => {
1522 if &sig.digest_prefix()[..] == &hash[..2] {
1523 // See if we can get the key for a
1524 // positive verification.
1525 if let Some(key) = $lookup_fn(&sig) {
1526 if let Ok(()) = sig.$verify_method(
1527 &key, self.primary.key(), $($verify_args),*)
1528 {
1529 $binding.$sigs.push(sig);
1530 } else {
1531 t!("Sig {:02X}{:02X}, type = {} \
1532 doesn't belong to {}",
1533 sig.digest_prefix()[0],
1534 sig.digest_prefix()[1],
1535 sig.typ(), $desc);
1536
1537 self.bad.push(sig);
1538 }
1539 } else {
1540 // No key, we need to trust our heuristic.
1541 sig.set_computed_digest(Some(hash));
1542 $binding.$sigs.push(sig);
1543 }
1544 } else {
1545 t!("Sig {:02X}{:02X}, type = {} \
1546 doesn't belong to {} (computed hash's prefix: {:02X}{:02X})",
1547 sig.digest_prefix()[0], sig.digest_prefix()[1],
1548 sig.typ(), $desc,
1549 hash[0], hash[1]);
1550
1551 self.bad.push(sig);
1552 }
1553 },
1554 Err(e) => {
1555 // Hashing failed, we likely don't support the
1556 // hash algorithm, or the signature type was
1557 // bad.
1558 t!("Sig {:02X}{:02X}, type = {}: {}",
1559 sig.digest_prefix()[0], sig.digest_prefix()[1],
1560 sig.typ(), e);
1561
1562 self.bad.push(sig);
1563 },
1564 }
1565 }
1566 });
1567 ($desc:expr, $binding:expr, $sigs:ident, $lookup_fn:expr,
1568 $verify_method:ident, $hash_method:ident, $sig_type_pat:pat) => ({
1569 check_3rd_party!($desc, $binding, $sigs, $lookup_fn,
1570 $verify_method, $hash_method, $sig_type_pat, )
1571 });
1572 }
1573
1574 // Placeholder lookup function.
1575 fn lookup_fn(_: &Signature)
1576 -> Option<Key<key::PublicParts, key::UnspecifiedRole>> {
1577 None
1578 }
1579
1580 check!("primary key",
1581 self.primary, self_signatures, hash_direct_key, DirectKey);
1582 check!("primary key",
1583 self.primary, self_revocations, hash_direct_key, KeyRevocation);
1584 check_3rd_party!("primary key",
1585 self.primary, certifications, lookup_fn,
1586 verify_direct_key, hash_direct_key, DirectKey);
1587 check_3rd_party!("primary key",
1588 self.primary, other_revocations, lookup_fn,
1589 verify_primary_key_revocation, hash_direct_key,
1590 KeyRevocation);
1591
1592 // Attestations are never associated with a primary key. If
1593 // there are any, they need to be reordered.
1594 self.bad.append(&mut self.primary.attestations.take());
1595
1596 for ua in self.userids.iter_mut() {
1597 check!(format!("userid \"{}\"",
1598 String::from_utf8_lossy(ua.userid().value())),
1599 ua, self_signatures, hash_userid_binding,
1600 GenericCertification | PersonaCertification
1601 | CasualCertification | PositiveCertification,
1602 ua.userid());
1603 check!(format!("userid \"{}\"",
1604 String::from_utf8_lossy(ua.userid().value())),
1605 ua, self_revocations, hash_userid_binding,
1606 CertificationRevocation,
1607 ua.userid());
1608 check!(format!("userid \"{}\"",
1609 String::from_utf8_lossy(ua.userid().value())),
1610 ua, attestations, hash_userid_approval,
1611 CertificationApproval,
1612 ua.userid());
1613 check_3rd_party!(
1614 format!("userid \"{}\"",
1615 String::from_utf8_lossy(ua.userid().value())),
1616 ua, certifications, lookup_fn,
1617 verify_userid_binding, hash_userid_binding,
1618 GenericCertification | PersonaCertification
1619 | CasualCertification | PositiveCertification,
1620 ua.userid());
1621 check_3rd_party!(
1622 format!("userid \"{}\"",
1623 String::from_utf8_lossy(ua.userid().value())),
1624 ua, other_revocations, lookup_fn,
1625 verify_userid_revocation, hash_userid_binding,
1626 CertificationRevocation,
1627 ua.userid());
1628 }
1629
1630 for binding in self.user_attributes.iter_mut() {
1631 check!("user attribute",
1632 binding, self_signatures, hash_user_attribute_binding,
1633 GenericCertification | PersonaCertification
1634 | CasualCertification | PositiveCertification,
1635 binding.user_attribute());
1636 check!("user attribute",
1637 binding, self_revocations, hash_user_attribute_binding,
1638 CertificationRevocation,
1639 binding.user_attribute());
1640 check!("user attribute",
1641 binding, attestations, hash_user_attribute_approval,
1642 CertificationApproval,
1643 binding.user_attribute());
1644 check_3rd_party!(
1645 "user attribute",
1646 binding, certifications, lookup_fn,
1647 verify_user_attribute_binding, hash_user_attribute_binding,
1648 GenericCertification | PersonaCertification
1649 | CasualCertification | PositiveCertification,
1650 binding.user_attribute());
1651 check_3rd_party!(
1652 "user attribute",
1653 binding, other_revocations, lookup_fn,
1654 verify_user_attribute_revocation, hash_user_attribute_binding,
1655 CertificationRevocation,
1656 binding.user_attribute());
1657 }
1658
1659 for binding in self.subkeys.iter_mut() {
1660 check!(format!("subkey {}", binding.key().keyid()),
1661 binding, self_signatures, hash_subkey_binding,
1662 SubkeyBinding,
1663 binding.key());
1664 check!(format!("subkey {}", binding.key().keyid()),
1665 binding, self_revocations, hash_subkey_binding,
1666 SubkeyRevocation,
1667 binding.key());
1668 check_3rd_party!(
1669 format!("subkey {}", binding.key().keyid()),
1670 binding, certifications, lookup_fn,
1671 verify_subkey_binding, hash_subkey_binding,
1672 SubkeyBinding,
1673 binding.key());
1674 check_3rd_party!(
1675 format!("subkey {}", binding.key().keyid()),
1676 binding, other_revocations, lookup_fn,
1677 verify_subkey_revocation, hash_subkey_binding,
1678 SubkeyRevocation,
1679 binding.key());
1680
1681 // Attestations are never associated with a subkey. If
1682 // there are any, they need to be reordered.
1683 self.bad.append(&mut binding.attestations.take());
1684 }
1685
1686 // See if the signatures that didn't validate are just out of
1687 // place.
1688 let mut bad_sigs: Vec<(Option<usize>, Signature)> =
1689 std::mem::take(&mut self.bad).into_iter()
1690 .map(|sig| {
1691 t!("We're going to reconsider bad signature {:?}", sig);
1692 (None, sig)
1693 })
1694 .collect();
1695 t!("Attempting to reorder {} signatures", bad_sigs.len());
1696
1697 // Do the same for signatures on unknown components, but
1698 // remember where we took them from.
1699 for (i, c) in self.unknowns.iter_mut().enumerate() {
1700 for sig in
1701 c.self_signatures.take().into_iter()
1702 .chain(
1703 std::mem::take(&mut c.certifications).into_iter())
1704 .chain(
1705 c.attestations.take().into_iter())
1706 .chain(
1707 c.self_revocations.take().into_iter())
1708 .chain(
1709 std::mem::take(&mut c.other_revocations).into_iter())
1710 {
1711 t!("We're going to reconsider {:?} on unknown component #{}",
1712 sig, i);
1713 bad_sigs.push((Some(i), sig));
1714 }
1715 }
1716
1717 let primary_fp: KeyHandle = self.key_handle();
1718
1719 'outer: for (unknown_idx, sig) in bad_sigs {
1720 // Did we find a new place for sig?
1721 let mut found_component = false;
1722
1723 // Is this signature a self-signature?
1724 let issuers =
1725 sig.get_issuers();
1726 let is_selfsig =
1727 issuers.is_empty()
1728 || issuers.iter().any(|kh| kh.aliases(&primary_fp));
1729
1730 macro_rules! check_one {
1731 ($desc:expr, // a description of the component
1732 $sigs:expr, // where to put $sig if successful
1733 $sig:ident, // the signature to check
1734 $hash_method:ident, // the method to compute the hash
1735 $($verify_args:expr),* // additional arguments for the above
1736 ) => ({
1737 if is_selfsig {
1738 t!("check_one!({}, {:?}, {:?}/{}, {}, ...)",
1739 $desc, $sigs, $sig, $sig.typ(),
1740 stringify!($hash_method));
1741 // Use hash prefix as heuristic.
1742 let key = self.primary.key();
1743 match $sig.hash_algo().context()
1744 .and_then(|ctx| {
1745 let mut ctx =
1746 ctx.for_signature($sig.version());
1747
1748 $sig.$hash_method(&mut ctx, key,
1749 $($verify_args),*)?;
1750 ctx.into_digest()
1751 })
1752 {
1753 Ok(hash) => {
1754 if &$sig.digest_prefix()[..] == &hash[..2] {
1755 t!("Sig {:02X}{:02X}, {:?} \
1756 was out of place. Likely belongs to {}.",
1757 $sig.digest_prefix()[0],
1758 $sig.digest_prefix()[1],
1759 $sig.typ(), $desc);
1760
1761 $sigs.push({
1762 let sig = $sig.clone();
1763 sig.set_computed_digest(Some(hash));
1764 sig
1765 });
1766
1767 // The cost of missing a revocation
1768 // certificate merely because we put
1769 // it into the wrong place seem to
1770 // outweigh the cost of duplicating
1771 // it.
1772 t!("Will keep trying to match this sig to \
1773 other components (found before? {:?})...",
1774 found_component);
1775 found_component = true;
1776 } else {
1777 t!("Sig {:02X}{:02X}, {:?} \
1778 does not belong to {}: \
1779 hash prefix mismatch {}",
1780 $sig.digest_prefix()[0],
1781 $sig.digest_prefix()[1],
1782 $sig.typ(), $desc,
1783 crate::fmt::hex::encode(&hash));
1784 }
1785 },
1786 Err(e) => {
1787 t!("Sig {:02X}{:02X}, type = {}: {}",
1788 $sig.digest_prefix()[0], $sig.digest_prefix()[1],
1789 $sig.typ(), e);
1790 },
1791 }
1792 }
1793 });
1794 ($desc:expr, $sigs:expr, $sig:ident,
1795 $hash_method:ident) => ({
1796 check_one!($desc, $sigs, $sig, $hash_method,)
1797 });
1798 }
1799
1800 // The same as check_one!, but for third party signatures.
1801 // If we do have the key that made the signature, we can
1802 // verify it like in check!. Otherwise, we use the hash
1803 // prefix as heuristic approximating the verification.
1804 macro_rules! check_one_3rd_party {
1805 ($desc:expr, // a description of the component
1806 $sigs:expr, // where to put $sig if successful
1807 $sig:ident, // the signature to check
1808 $lookup_fn:expr, // a function to lookup keys
1809 $verify_method:ident, // the method to verify it
1810 $hash_method:ident, // the method to compute the hash
1811 $($verify_args:expr),* // additional arguments for the above
1812 ) => ({
1813 if ! is_selfsig {
1814 t!("check_one_3rd_party!({}, {}, {:?}, {}, {}, ...)",
1815 $desc, stringify!($sigs), $sig,
1816 stringify!($verify_method), stringify!($hash_method));
1817 if let Some(key) = $lookup_fn(&$sig) {
1818 match $sig.$verify_method(&key,
1819 self.primary.key(),
1820 $($verify_args),*)
1821 {
1822 Ok(()) => {
1823 t!("Sig {:02X}{:02X}, {:?} \
1824 was out of place. Belongs to {}.",
1825 $sig.digest_prefix()[0],
1826 $sig.digest_prefix()[1],
1827 $sig.typ(), $desc);
1828
1829 $sigs.push($sig);
1830 continue 'outer;
1831 },
1832 Err(err) => {
1833 t!("Sig {:02X}{:02X}, type = {} \
1834 doesn't belong to {}: {:?}",
1835 $sig.digest_prefix()[0], $sig.digest_prefix()[1],
1836 $sig.typ(), $desc, err);
1837 },
1838 }
1839 } else {
1840 // Use hash prefix as heuristic.
1841 let key = self.primary.key();
1842 match $sig.hash_algo().context()
1843 .and_then(|ctx| {
1844 let mut ctx =
1845 ctx.for_signature($sig.version());
1846 $sig.$hash_method(&mut ctx, key,
1847 $($verify_args),*)?;
1848 ctx.into_digest()
1849 })
1850 {
1851 Ok(hash) => {
1852 if &$sig.digest_prefix()[..] == &hash[..2] {
1853 t!("Sig {:02X}{:02X}, {:?} \
1854 was out of place. Likely belongs to {}.",
1855 $sig.digest_prefix()[0],
1856 $sig.digest_prefix()[1],
1857 $sig.typ(), $desc);
1858
1859 $sigs.push({
1860 let sig = $sig.clone();
1861 sig.set_computed_digest(Some(hash));
1862 sig
1863 });
1864
1865 // The cost of missing a revocation
1866 // certificate merely because we put
1867 // it into the wrong place seem to
1868 // outweigh the cost of duplicating
1869 // it.
1870 t!("Will keep trying to match this sig to \
1871 other components (found before? {:?})...",
1872 found_component);
1873 found_component = true;
1874 } else {
1875 t!("Sig {:02X}{:02X}, {:?} \
1876 does not belong to {}: \
1877 hash prefix mismatch {}",
1878 $sig.digest_prefix()[0],
1879 $sig.digest_prefix()[1],
1880 $sig.typ(), $desc,
1881 crate::fmt::hex::encode(&hash));
1882 }
1883 },
1884 Err(e) => {
1885 t!("Sig {:02X}{:02X}, type = {}: {}",
1886 $sig.digest_prefix()[0], $sig.digest_prefix()[1],
1887 $sig.typ(), e);
1888 },
1889 }
1890 }
1891 }
1892 });
1893 ($desc:expr, $sigs:expr, $sig:ident, $lookup_fn:expr,
1894 $verify_method:ident, $hash_method:ident) => ({
1895 check_one_3rd_party!($desc, $sigs, $sig, $lookup_fn,
1896 $verify_method, $hash_method, )
1897 });
1898 }
1899
1900 match sig.typ() {
1901 DirectKey => {
1902 check_one!("primary key", self.primary.self_signatures,
1903 sig, hash_direct_key);
1904 check_one_3rd_party!(
1905 "primary key", self.primary.certifications, sig,
1906 lookup_fn,
1907 verify_direct_key, hash_direct_key);
1908 },
1909
1910 KeyRevocation => {
1911 check_one!("primary key", self.primary.self_revocations,
1912 sig, hash_direct_key);
1913 check_one_3rd_party!(
1914 "primary key", self.primary.other_revocations, sig,
1915 lookup_fn, verify_primary_key_revocation,
1916 hash_direct_key);
1917 },
1918
1919 GenericCertification | PersonaCertification
1920 | CasualCertification | PositiveCertification =>
1921 {
1922 for binding in self.userids.iter_mut() {
1923 check_one!(format!("userid \"{}\"",
1924 String::from_utf8_lossy(
1925 binding.userid().value())),
1926 binding.self_signatures, sig,
1927 hash_userid_binding, binding.userid());
1928 check_one_3rd_party!(
1929 format!("userid \"{}\"",
1930 String::from_utf8_lossy(
1931 binding.userid().value())),
1932 binding.certifications, sig, lookup_fn,
1933 verify_userid_binding, hash_userid_binding,
1934 binding.userid());
1935 }
1936
1937 for binding in self.user_attributes.iter_mut() {
1938 check_one!("user attribute",
1939 binding.self_signatures, sig,
1940 hash_user_attribute_binding,
1941 binding.user_attribute());
1942 check_one_3rd_party!(
1943 "user attribute",
1944 binding.certifications, sig, lookup_fn,
1945 verify_user_attribute_binding,
1946 hash_user_attribute_binding,
1947 binding.user_attribute());
1948 }
1949 },
1950
1951 crate::types::SignatureType::CertificationApproval => {
1952 for binding in self.userids.iter_mut() {
1953 check_one!(format!("userid \"{}\"",
1954 String::from_utf8_lossy(
1955 binding.userid().value())),
1956 binding.attestations, sig,
1957 hash_userid_approval, binding.userid());
1958 }
1959
1960 for binding in self.user_attributes.iter_mut() {
1961 check_one!("user attribute",
1962 binding.attestations, sig,
1963 hash_user_attribute_approval,
1964 binding.user_attribute());
1965 }
1966 },
1967
1968 CertificationRevocation => {
1969 for binding in self.userids.iter_mut() {
1970 check_one!(format!("userid \"{}\"",
1971 String::from_utf8_lossy(
1972 binding.userid().value())),
1973 binding.self_revocations, sig,
1974 hash_userid_binding,
1975 binding.userid());
1976 check_one_3rd_party!(
1977 format!("userid \"{}\"",
1978 String::from_utf8_lossy(
1979 binding.userid().value())),
1980 binding.other_revocations, sig, lookup_fn,
1981 verify_userid_revocation, hash_userid_binding,
1982 binding.userid());
1983 }
1984
1985 for binding in self.user_attributes.iter_mut() {
1986 check_one!("user attribute",
1987 binding.self_revocations, sig,
1988 hash_user_attribute_binding,
1989 binding.user_attribute());
1990 check_one_3rd_party!(
1991 "user attribute",
1992 binding.other_revocations, sig, lookup_fn,
1993 verify_user_attribute_revocation,
1994 hash_user_attribute_binding,
1995 binding.user_attribute());
1996 }
1997 },
1998
1999 SubkeyBinding => {
2000 for binding in self.subkeys.iter_mut() {
2001 check_one!(format!("subkey {}", binding.key().keyid()),
2002 binding.self_signatures, sig,
2003 hash_subkey_binding, binding.key());
2004 check_one_3rd_party!(
2005 format!("subkey {}", binding.key().keyid()),
2006 binding.certifications, sig, lookup_fn,
2007 verify_subkey_binding, hash_subkey_binding,
2008 binding.key());
2009 }
2010 },
2011
2012 SubkeyRevocation => {
2013 for binding in self.subkeys.iter_mut() {
2014 check_one!(format!("subkey {}", binding.key().keyid()),
2015 binding.self_revocations, sig,
2016 hash_subkey_binding, binding.key());
2017 check_one_3rd_party!(
2018 format!("subkey {}", binding.key().keyid()),
2019 binding.other_revocations, sig, lookup_fn,
2020 verify_subkey_revocation, hash_subkey_binding,
2021 binding.key());
2022 }
2023 },
2024
2025 typ => {
2026 t!("Odd signature type: {:?}", typ);
2027 },
2028 }
2029
2030 if found_component {
2031 continue;
2032 }
2033
2034 // Keep them for later.
2035 t!("{} {:02X}{:02X}, {:?}, originally found on {:?} \
2036 doesn't belong to any known component or is bad.",
2037 if is_selfsig { "Self-sig" } else { "3rd-party-sig" },
2038 sig.digest_prefix()[0], sig.digest_prefix()[1],
2039 sig.typ(), unknown_idx);
2040
2041 if let Some(i) = unknown_idx {
2042 let is_revocation = match sig.typ() {
2043 CertificationRevocation | KeyRevocation | SubkeyRevocation
2044 => true,
2045 _ => false,
2046 };
2047 match (is_selfsig, is_revocation) {
2048 (false, false) =>
2049 self.unknowns[i].certifications.push(sig),
2050 (false, true) =>
2051 self.unknowns[i].other_revocations.push(sig),
2052 (true, false) =>
2053 self.unknowns[i].self_signatures.push(sig),
2054 (true, true) =>
2055 self.unknowns[i].self_revocations.push(sig),
2056 }
2057 } else {
2058 self.bad.push(sig);
2059 }
2060 }
2061
2062 if !self.bad.is_empty() {
2063 t!("{}: ignoring {} bad self signatures",
2064 self.keyid(), self.bad.len());
2065 }
2066
2067 // Sort again. We may have moved signatures to the right
2068 // component, and we need to ensure they are in the right spot
2069 // (i.e. newest first).
2070 self.sort_and_dedup();
2071
2072 // XXX: Check if the sigs in other_sigs issuer are actually
2073 // designated revokers for this key (listed in a "Revocation
2074 // Key" subpacket in *any* non-revoked self signature). Only
2075 // if that is the case should a sig be considered a potential
2076 // revocation. (This applies to
2077 // self.primary_other_revocations as well as
2078 // self.userids().other_revocations, etc.) If not, put the
2079 // sig on the bad list.
2080 //
2081 // Note: just because the Cert doesn't indicate that a key is a
2082 // designed revoker doesn't mean that it isn't---we might just
2083 // be missing the signature. In other words, this is a policy
2084 // decision, but given how easy it could be to create rogue
2085 // revocations, is probably the better to reject such
2086 // signatures than to keep them around and have many keys
2087 // being shown as "potentially revoked".
2088
2089 // XXX Do some more canonicalization.
2090
2091 self
2092 }
2093
2094 /// Returns the certificate's fingerprint as a `KeyHandle`.
2095 ///
2096 /// # Examples
2097 ///
2098 /// ```
2099 /// # use sequoia_openpgp as openpgp;
2100 /// # use openpgp::cert::prelude::*;
2101 /// # use openpgp::KeyHandle;
2102 /// #
2103 /// # fn main() -> openpgp::Result<()> {
2104 /// # let (cert, _) =
2105 /// # CertBuilder::general_purpose(Some("alice@example.org"))
2106 /// # .generate()?;
2107 /// #
2108 /// println!("{}", cert.key_handle());
2109 ///
2110 /// // This always returns a fingerprint.
2111 /// match cert.key_handle() {
2112 /// KeyHandle::Fingerprint(_) => (),
2113 /// KeyHandle::KeyID(_) => unreachable!(),
2114 /// }
2115 /// #
2116 /// # Ok(())
2117 /// # }
2118 /// ```
2119 pub fn key_handle(&self) -> KeyHandle {
2120 self.primary.key().key_handle()
2121 }
2122
2123 /// Returns the certificate's fingerprint.
2124 ///
2125 /// # Examples
2126 ///
2127 /// ```
2128 /// # use sequoia_openpgp as openpgp;
2129 /// # use openpgp::cert::prelude::*;
2130 /// #
2131 /// # fn main() -> openpgp::Result<()> {
2132 /// # let (cert, _) =
2133 /// # CertBuilder::general_purpose(Some("alice@example.org"))
2134 /// # .generate()?;
2135 /// #
2136 /// println!("{}", cert.fingerprint());
2137 /// #
2138 /// # Ok(())
2139 /// # }
2140 /// ```
2141 pub fn fingerprint(&self) -> Fingerprint {
2142 self.primary.key().fingerprint()
2143 }
2144
2145 /// Returns the certificate's Key ID.
2146 ///
2147 /// As a general rule of thumb, you should prefer the fingerprint
2148 /// as it is possible to create keys with a colliding Key ID using
2149 /// a [birthday attack].
2150 ///
2151 /// [birthday attack]: https://nullprogram.com/blog/2019/07/22/
2152 ///
2153 /// # Examples
2154 ///
2155 /// ```
2156 /// # use sequoia_openpgp as openpgp;
2157 /// # use openpgp::cert::prelude::*;
2158 /// #
2159 /// # fn main() -> openpgp::Result<()> {
2160 /// # let (cert, _) =
2161 /// # CertBuilder::general_purpose(Some("alice@example.org"))
2162 /// # .generate()?;
2163 /// #
2164 /// println!("{}", cert.keyid());
2165 /// #
2166 /// # Ok(())
2167 /// # }
2168 /// ```
2169 pub fn keyid(&self) -> KeyID {
2170 self.primary.key().keyid()
2171 }
2172
2173 /// Merges `other` into `self`, ignoring secret key material in
2174 /// `other`.
2175 ///
2176 /// If `other` is a different certificate, then an error is
2177 /// returned.
2178 ///
2179 /// Merging two versions of a certificate is complicated, because
2180 /// there may be multiple variants of the same key or signature
2181 /// packet. It is possible to have multiple variants of a key
2182 /// packet if one contains secret key material, and the other
2183 /// does not, or if both contain secret key material that is
2184 /// protected in different ways, e.g., a different algorithm, or a
2185 /// different password. Multiple variants of a signature packet
2186 /// are possible when the unhashed subpacket areas differ.
2187 ///
2188 /// This routine is different from [`Cert::insert_packets`] in the
2189 /// following ways:
2190 ///
2191 /// - `Cert::merge_public` strictly prefers keys in `self` to
2192 /// those in `other`. That is, if a primary key or subkey
2193 /// appears in both `self` and `other`, the version in `self`
2194 /// is kept. In contrast, [`Cert::insert_packets`] prefers
2195 /// the new variant.
2196 ///
2197 /// - If `other` contains a new subkey, `Cert::merge_public`
2198 /// merges it into the certificate, but strips any secret key
2199 /// material. In contrast, [`Cert::insert_packets`] preserves
2200 /// the secret key material.
2201 ///
2202 /// - If both `self` and `other` contain two variants of a
2203 /// signature (that is, a signature packet that is identical
2204 /// expect for the contents of the unhashed subpacket area),
2205 /// `Cert::merge_public` merges the two variants using
2206 /// [`Signature::merge`], which combines the unhashed
2207 /// subpacket areas. [`Cert::insert_packets`] just takes the
2208 /// new signature packet.
2209 ///
2210 /// This function is appropriate to merge certificate material
2211 /// from untrusted sources like keyservers, because it only adds
2212 /// data to the existing certificate, it never overwrites existing
2213 /// data, and it doesn't import secret key material, which may
2214 /// have been manipulated by an attacker.
2215 ///
2216 /// [`Cert::merge_public_and_secret`] is similar to this function,
2217 /// but merges in secret key material from `other`.
2218 ///
2219 /// # Examples
2220 ///
2221 /// Merge a certificate from an untrusted source:
2222 ///
2223 /// ```
2224 /// # use sequoia_openpgp as openpgp;
2225 /// # use openpgp::cert::prelude::*;
2226 /// #
2227 /// # fn main() -> openpgp::Result<()> {
2228 /// # let (local, _) =
2229 /// # CertBuilder::general_purpose(Some("alice@example.org"))
2230 /// # .generate()?;
2231 /// # let keyserver = local.clone();
2232 /// // Merge the local version with the version from the keyserver.
2233 /// let cert = local.merge_public(keyserver)?;
2234 /// # let _ = cert;
2235 /// # Ok(()) }
2236 /// ```
2237 ///
2238 /// Secret key material in `other` is stripped, even if the
2239 /// variant of the packet in `self` doesn't have secret key
2240 /// material:
2241 ///
2242 /// ```
2243 /// use sequoia_openpgp as openpgp;
2244 /// use openpgp::cert::CertBuilder;
2245 ///
2246 /// # fn main() -> openpgp::Result<()> {
2247 /// // Create a new key.
2248 /// let (cert, rev) =
2249 /// CertBuilder::general_purpose(Some("alice@example.org"))
2250 /// .generate()?;
2251 /// assert!(cert.is_tsk());
2252 ///
2253 /// let stripped = cert.clone().strip_secret_key_material();
2254 /// assert!(! stripped.is_tsk());
2255 ///
2256 /// // Merge `cert` into `stripped`.
2257 /// let merged = stripped.merge_public(cert).expect("same certificate");
2258 /// assert!(! merged.is_tsk());
2259 ///
2260 /// # Ok(()) }
2261 /// ```
2262 ///
2263 /// Secret key material from `self` is preferred to secret key
2264 /// material from `other`:
2265 ///
2266 /// ```
2267 /// use sequoia_openpgp as openpgp;
2268 /// use openpgp::crypto::Password;
2269 /// use openpgp::cert::prelude::*;
2270 /// use openpgp::Packet;
2271 ///
2272 /// # fn main() -> openpgp::Result<()> {
2273 /// let p0 = Password::from("old password");
2274 /// let p1 = Password::from("new password");
2275 ///
2276 /// // Create a new key.
2277 /// let (cert, rev) =
2278 /// CertBuilder::general_purpose(Some("alice@example.org"))
2279 /// .set_password(Some(p0.clone()))
2280 /// .generate()?;
2281 /// assert!(cert.is_tsk());
2282 ///
2283 /// // Change the password for the primary key.
2284 /// let pk = cert.primary_key().key().clone().parts_into_secret()?
2285 /// .decrypt_secret(&p0)?
2286 /// .encrypt_secret(&p1)?;
2287 /// let other = Cert::try_from(vec![ Packet::from(pk) ])
2288 /// .expect("a primary key is a certificate");
2289 ///
2290 /// // Merge `other` into `cert`.
2291 /// let merged = cert.merge_public(other).expect("same certificate");
2292 ///
2293 /// // `merged` has the secret key material from `cert`, which is
2294 /// // password protected with `p0`, not `other`, which is password
2295 /// // protected with `p1`.
2296 /// assert!(merged.primary_key().key().clone().parts_into_secret()?
2297 /// .decrypt_secret(&p0).is_ok());
2298 /// # Ok(()) }
2299 /// ```
2300 ///
2301 /// The unhashed subpacket areas of two variants of a signature
2302 /// are merged:
2303 ///
2304 /// ```
2305 /// use sequoia_openpgp as openpgp;
2306 /// use openpgp::Packet;
2307 /// use openpgp::cert::prelude::*;
2308 /// use openpgp::packet::signature::subpacket::Subpacket;
2309 /// use openpgp::packet::signature::subpacket::SubpacketTag;
2310 /// use openpgp::packet::signature::subpacket::SubpacketValue;
2311 ///
2312 /// # fn main() -> openpgp::Result<()> {
2313 /// // Create a new key.
2314 /// let (cert, rev) =
2315 /// CertBuilder::general_purpose(Some("alice@example.org"))
2316 /// .generate()?;
2317 /// assert!(cert.is_tsk());
2318 ///
2319 /// // Add a subpacket to the unhashed subpacket area.
2320 /// let subpacket_a = Subpacket::new(
2321 /// SubpacketValue::Unknown {
2322 /// tag: SubpacketTag::Private(100),
2323 /// body: Vec::new(),
2324 /// },
2325 /// false).expect("valid");
2326 /// let subpacket_b = Subpacket::new(
2327 /// SubpacketValue::Unknown {
2328 /// tag: SubpacketTag::Private(101),
2329 /// body: Vec::new(),
2330 /// },
2331 /// false).expect("valid");
2332 ///
2333 /// let mut cert_a = cert.clone().into_packets().collect::<Vec<Packet>>();
2334 /// match cert_a[1] {
2335 /// Packet::Signature(ref mut sig) => {
2336 /// let unhashed_area = sig.unhashed_area_mut();
2337 /// assert!(unhashed_area.subpacket(subpacket_a.tag()).is_none());
2338 /// assert!(unhashed_area.subpacket(subpacket_b.tag()).is_none());
2339 /// unhashed_area.add(subpacket_a.clone());
2340 /// }
2341 /// _ => panic!("Second packet is the direct signature packet."),
2342 /// };
2343 /// let cert_a = Cert::try_from(cert_a).expect("valid");
2344 ///
2345 /// let mut cert_b = cert.clone().into_packets().collect::<Vec<Packet>>();
2346 /// match cert_b[1] {
2347 /// Packet::Signature(ref mut sig) => {
2348 /// let unhashed_area = sig.unhashed_area_mut();
2349 /// assert!(unhashed_area.subpacket(subpacket_a.tag()).is_none());
2350 /// assert!(unhashed_area.subpacket(subpacket_b.tag()).is_none());
2351 /// unhashed_area.add(subpacket_b.clone());
2352 /// }
2353 /// _ => panic!("Second packet is the direct signature packet."),
2354 /// };
2355 /// let cert_b = Cert::try_from(cert_b).expect("valid");
2356 ///
2357 /// // When we merge `cert_b` into `cert_a`, the signature packets
2358 /// // are merged:
2359 /// let merged = cert_a.clone().merge_public(cert_b.clone())
2360 /// .expect("same certificate")
2361 /// .into_packets()
2362 /// .collect::<Vec<Packet>>();
2363 /// match merged[1] {
2364 /// Packet::Signature(ref sig) => {
2365 /// let unhashed_area = sig.unhashed_area();
2366 /// assert!(unhashed_area.subpacket(subpacket_a.tag()).is_some());
2367 /// assert!(unhashed_area.subpacket(subpacket_b.tag()).is_some());
2368 /// }
2369 /// _ => panic!("Second packet is the direct signature packet."),
2370 /// };
2371 ///
2372 /// // Likewise, when we merge `cert_a` into `cert_b`, the signature
2373 /// // packets are merged:
2374 /// let merged = cert_b.clone().merge_public(cert_a.clone())
2375 /// .expect("same certificate")
2376 /// .into_packets()
2377 /// .collect::<Vec<Packet>>();
2378 /// match merged[1] {
2379 /// Packet::Signature(ref sig) => {
2380 /// let unhashed_area = sig.unhashed_area();
2381 /// assert!(unhashed_area.subpacket(subpacket_a.tag()).is_some());
2382 /// assert!(unhashed_area.subpacket(subpacket_b.tag()).is_some());
2383 /// }
2384 /// _ => panic!("Second packet is the direct signature packet."),
2385 /// };
2386 /// # Ok(()) }
2387 /// ```
2388 pub fn merge_public(self, other: Cert) -> Result<Self> {
2389 // Strip all secrets from `other`.
2390 let other_public = other.strip_secret_key_material();
2391 // Then merge it.
2392 self.merge_public_and_secret(other_public)
2393 }
2394
2395 /// Merges `other` into `self`, including secret key material.
2396 ///
2397 /// If `other` is a different certificate, then an error is
2398 /// returned.
2399 ///
2400 /// This function is like [`Cert::merge_public`] except:
2401 ///
2402 /// - if two variants of the same key have secret key material,
2403 /// then the version in `other` is preferred,
2404 ///
2405 /// - if there are two variants of the same key, and one has
2406 /// secret key material, that variant is preferred.
2407 ///
2408 /// This is different from [`Cert::insert_packets`], which
2409 /// unconditionally prefers keys in the packets that are being
2410 /// merged into the certificate.
2411 ///
2412 /// It is important to only merge key material from trusted
2413 /// sources using this function, because it may be used to import
2414 /// secret key material. Secret key material is not authenticated
2415 /// by OpenPGP, and there are plausible attack scenarios where a
2416 /// malicious actor injects secret key material.
2417 ///
2418 /// To merge only public key material, which is always safe, use
2419 /// [`Cert::merge_public`].
2420 ///
2421 /// # Examples
2422 ///
2423 /// Merge a certificate from a trusted source:
2424 ///
2425 /// ```
2426 /// # use sequoia_openpgp as openpgp;
2427 /// # use openpgp::cert::prelude::*;
2428 /// #
2429 /// # fn main() -> openpgp::Result<()> {
2430 /// # let (local, _) =
2431 /// # CertBuilder::general_purpose(Some("alice@example.org"))
2432 /// # .generate()?;
2433 /// # let other_device = local.clone();
2434 /// // Merge the local version with the version from your other device.
2435 /// let cert = local.merge_public_and_secret(other_device)?;
2436 /// # let _ = cert;
2437 /// # Ok(()) }
2438 /// ```
2439 ///
2440 /// Secret key material is preferred to no secret key material:
2441 ///
2442 /// ```
2443 /// use sequoia_openpgp as openpgp;
2444 /// use openpgp::cert::CertBuilder;
2445 ///
2446 /// # fn main() -> openpgp::Result<()> {
2447 /// // Create a new key.
2448 /// let (cert, rev) =
2449 /// CertBuilder::general_purpose(Some("alice@example.org"))
2450 /// .generate()?;
2451 /// assert!(cert.is_tsk());
2452 ///
2453 /// let stripped = cert.clone().strip_secret_key_material();
2454 /// assert!(! stripped.is_tsk());
2455 ///
2456 /// // If we merge `cert` into `stripped`, the secret key material is
2457 /// // preserved:
2458 /// let merged = stripped.clone().merge_public_and_secret(cert.clone())
2459 /// .expect("same certificate");
2460 /// assert!(merged.is_tsk());
2461 ///
2462 /// // Likewise if we merge `stripped` into `cert`:
2463 /// let merged = cert.merge_public_and_secret(stripped)
2464 /// .expect("same certificate");
2465 /// assert!(merged.is_tsk());
2466 ///
2467 /// # Ok(()) }
2468 /// ```
2469 ///
2470 /// Secret key material in `other` is preferred:
2471 ///
2472 /// ```
2473 /// use sequoia_openpgp as openpgp;
2474 /// use openpgp::crypto::Password;
2475 /// use openpgp::cert::prelude::*;
2476 /// use openpgp::Packet;
2477 ///
2478 /// # fn main() -> openpgp::Result<()> {
2479 /// let p0 = Password::from("old password");
2480 /// let p1 = Password::from("new password");
2481 ///
2482 /// // Create a new key.
2483 /// let (cert, rev) =
2484 /// CertBuilder::general_purpose(Some("alice@example.org"))
2485 /// .set_password(Some(p0.clone()))
2486 /// .generate()?;
2487 /// assert!(cert.is_tsk());
2488 ///
2489 /// // Change the password for the primary key.
2490 /// let pk = cert.primary_key().key().clone().parts_into_secret()?
2491 /// .decrypt_secret(&p0)?
2492 /// .encrypt_secret(&p1)?;
2493 /// let other = Cert::try_from(vec![ Packet::from(pk) ])
2494 /// .expect("a primary key is a certificate");
2495 ///
2496 /// // Merge `other` into `cert`.
2497 /// let merged = cert.merge_public_and_secret(other).expect("same certificate");
2498 ///
2499 /// // `merged` has the secret key material from `other`, which is
2500 /// // password protected with `p1`, not `self`, which is password
2501 /// // protected with `p0`.
2502 /// assert!(merged.primary_key().key().clone().parts_into_secret()?
2503 /// .decrypt_secret(&p1).is_ok());
2504 /// # Ok(()) }
2505 /// ```
2506 ///
2507 /// The unhashed subpacket areas of two variants of a signature
2508 /// are merged:
2509 ///
2510 /// ```
2511 /// use sequoia_openpgp as openpgp;
2512 /// use openpgp::Packet;
2513 /// use openpgp::cert::prelude::*;
2514 /// use openpgp::packet::signature::subpacket::Subpacket;
2515 /// use openpgp::packet::signature::subpacket::SubpacketTag;
2516 /// use openpgp::packet::signature::subpacket::SubpacketValue;
2517 ///
2518 /// # fn main() -> openpgp::Result<()> {
2519 /// // Create a new key.
2520 /// let (cert, rev) =
2521 /// CertBuilder::general_purpose(Some("alice@example.org"))
2522 /// .generate()?;
2523 /// assert!(cert.is_tsk());
2524 ///
2525 /// // Add a subpacket to the unhashed subpacket area.
2526 /// let subpacket_a = Subpacket::new(
2527 /// SubpacketValue::Unknown {
2528 /// tag: SubpacketTag::Private(100),
2529 /// body: Vec::new(),
2530 /// },
2531 /// false).expect("valid");
2532 /// let subpacket_b = Subpacket::new(
2533 /// SubpacketValue::Unknown {
2534 /// tag: SubpacketTag::Private(101),
2535 /// body: Vec::new(),
2536 /// },
2537 /// false).expect("valid");
2538 ///
2539 /// let mut cert_a = cert.clone().into_packets().collect::<Vec<Packet>>();
2540 /// match cert_a[1] {
2541 /// Packet::Signature(ref mut sig) => {
2542 /// let unhashed_area = sig.unhashed_area_mut();
2543 /// assert!(unhashed_area.subpacket(subpacket_a.tag()).is_none());
2544 /// assert!(unhashed_area.subpacket(subpacket_b.tag()).is_none());
2545 /// unhashed_area.add(subpacket_a.clone());
2546 /// }
2547 /// _ => panic!("Second packet is the direct signature packet."),
2548 /// };
2549 /// let cert_a = Cert::try_from(cert_a).expect("valid");
2550 ///
2551 /// let mut cert_b = cert.clone().into_packets().collect::<Vec<Packet>>();
2552 /// match cert_b[1] {
2553 /// Packet::Signature(ref mut sig) => {
2554 /// let unhashed_area = sig.unhashed_area_mut();
2555 /// assert!(unhashed_area.subpacket(subpacket_a.tag()).is_none());
2556 /// assert!(unhashed_area.subpacket(subpacket_b.tag()).is_none());
2557 /// unhashed_area.add(subpacket_b.clone());
2558 /// }
2559 /// _ => panic!("Second packet is the direct signature packet."),
2560 /// };
2561 /// let cert_b = Cert::try_from(cert_b).expect("valid");
2562 ///
2563 /// // When we merge `cert_b` into `cert_a`, the signature packets
2564 /// // are merged:
2565 /// let merged = cert_a.clone().merge_public_and_secret(cert_b.clone())
2566 /// .expect("same certificate")
2567 /// .into_packets()
2568 /// .collect::<Vec<Packet>>();
2569 /// match merged[1] {
2570 /// Packet::Signature(ref sig) => {
2571 /// let unhashed_area = sig.unhashed_area();
2572 /// assert!(unhashed_area.subpacket(subpacket_a.tag()).is_some());
2573 /// assert!(unhashed_area.subpacket(subpacket_b.tag()).is_some());
2574 /// }
2575 /// _ => panic!("Second packet is the direct signature packet."),
2576 /// };
2577 ///
2578 /// // Likewise, when we merge `cert_a` into `cert_b`, the signature
2579 /// // packets are merged:
2580 /// let merged = cert_b.clone().merge_public_and_secret(cert_a.clone())
2581 /// .expect("same certificate")
2582 /// .into_packets()
2583 /// .collect::<Vec<Packet>>();
2584 /// match merged[1] {
2585 /// Packet::Signature(ref sig) => {
2586 /// let unhashed_area = sig.unhashed_area();
2587 /// assert!(unhashed_area.subpacket(subpacket_a.tag()).is_some());
2588 /// assert!(unhashed_area.subpacket(subpacket_b.tag()).is_some());
2589 /// }
2590 /// _ => panic!("Second packet is the direct signature packet."),
2591 /// };
2592 /// # Ok(()) }
2593 /// ```
2594 pub fn merge_public_and_secret(mut self, mut other: Cert) -> Result<Self> {
2595 if self.fingerprint() != other.fingerprint() {
2596 // The primary key is not the same. There is nothing to
2597 // do.
2598 return Err(Error::InvalidArgument(
2599 "Primary key mismatch".into()).into());
2600 }
2601
2602 // Prefer the secret in `other`.
2603 if other.primary.key().has_secret() {
2604 std::mem::swap(self.primary.key_mut(), other.primary.key_mut());
2605 }
2606
2607 self.primary.self_signatures.append(
2608 &mut other.primary.self_signatures);
2609 self.primary.attestations.append(
2610 &mut other.primary.attestations);
2611 self.primary.certifications.append(
2612 &mut other.primary.certifications);
2613 self.primary.self_revocations.append(
2614 &mut other.primary.self_revocations);
2615 self.primary.other_revocations.append(
2616 &mut other.primary.other_revocations);
2617
2618 self.userids.append(&mut other.userids);
2619 self.user_attributes.append(&mut other.user_attributes);
2620 self.subkeys.append(&mut other.subkeys);
2621 self.bad.append(&mut other.bad);
2622
2623 Ok(self.canonicalize())
2624 }
2625
2626 // Returns whether the specified packet is a valid start of a
2627 // certificate.
2628 fn valid_start<T>(tag: T) -> Result<()>
2629 where T: Into<Tag>
2630 {
2631 let tag = tag.into();
2632 match tag {
2633 Tag::SecretKey | Tag::PublicKey => Ok(()),
2634 _ => Err(Error::MalformedCert(
2635 format!("A certificate does not start with a {}",
2636 tag)).into()),
2637 }
2638 }
2639
2640 // Returns whether the specified packet can occur in a
2641 // certificate.
2642 //
2643 // This function rejects all packets that are known to not belong
2644 // in a certificate. It conservatively accepts unknown packets
2645 // based on the assumption that they are some new component type
2646 // from the future.
2647 fn valid_packet<T>(tag: T) -> Result<()>
2648 where T: Into<Tag>
2649 {
2650 let tag = tag.into();
2651 match tag {
2652 // Packets that definitely don't belong in a certificate.
2653 Tag::Reserved
2654 | Tag::PKESK
2655 | Tag::SKESK
2656 | Tag::OnePassSig
2657 | Tag::CompressedData
2658 | Tag::SED
2659 | Tag::Literal
2660 | Tag::SEIP
2661 | Tag::MDC
2662 | Tag::AED =>
2663 {
2664 Err(Error::MalformedCert(
2665 format!("A certificate cannot not include a {}",
2666 tag)).into())
2667 }
2668 // The rest either definitely belong in a certificate or
2669 // are unknown (and conservatively accepted for future
2670 // compatibility).
2671 _ => Ok(()),
2672 }
2673 }
2674
2675 /// Adds packets to the certificate.
2676 ///
2677 /// This function turns the certificate into a sequence of
2678 /// packets, appends the packets to the end of it, and
2679 /// canonicalizes the result. [Known packets that don't belong in
2680 /// a TPK or TSK] cause this function to return an error. Unknown
2681 /// packets are retained and added to the list of [unknown
2682 /// components]. The goal is to provide some future
2683 /// compatibility.
2684 ///
2685 /// If a key is merged that already exists in the certificate, it
2686 /// replaces the existing key. This way, secret key material can
2687 /// be added, removed, encrypted, or decrypted.
2688 ///
2689 /// Similarly, if a signature is merged that already exists in the
2690 /// certificate, it replaces the existing signature. This way,
2691 /// the unhashed subpacket area can be updated.
2692 ///
2693 /// On success, this function returns the certificate with the
2694 /// packets merged in, and a boolean indicating whether the
2695 /// certificate actually changed. Changed here means that at
2696 /// least one new packet was added, or an existing packet was
2697 /// updated. Alternatively, changed means that the serialized
2698 /// form has changed.
2699 ///
2700 /// [Known packets that don't belong in a TPK or TSK]: https://www.rfc-editor.org/rfc/rfc9580.html#section-10
2701 /// [unknown components]: Cert::unknowns()
2702 ///
2703 /// # Examples
2704 ///
2705 /// ```
2706 /// use sequoia_openpgp as openpgp;
2707 /// use openpgp::cert::prelude::*;
2708 /// use openpgp::packet::prelude::*;
2709 /// use openpgp::serialize::Serialize;
2710 /// use openpgp::parse::Parse;
2711 /// use openpgp::types::DataFormat;
2712 ///
2713 /// # fn main() -> openpgp::Result<()> {
2714 /// // Create a new key.
2715 /// let (cert, rev) =
2716 /// CertBuilder::general_purpose(Some("alice@example.org"))
2717 /// .generate()?;
2718 /// assert!(cert.is_tsk());
2719 ///
2720 ///
2721 /// // Merging in the certificate doesn't change it.
2722 /// let identical_cert = cert.clone();
2723 /// let (cert, changed) =
2724 /// cert.insert_packets(identical_cert.into_tsk().into_packets())?;
2725 /// assert!(! changed);
2726 ///
2727 ///
2728 /// // Merge in the revocation certificate.
2729 /// assert_eq!(cert.primary_key().self_revocations().count(), 0);
2730 /// let (cert, changed) = cert.insert_packets(rev)?;
2731 /// assert!(changed);
2732 /// assert_eq!(cert.primary_key().self_revocations().count(), 1);
2733 ///
2734 ///
2735 /// // Add an unknown packet.
2736 /// let tag = Tag::Private(61.into());
2737 /// let unknown = Unknown::new(tag,
2738 /// openpgp::Error::UnsupportedPacketType(tag).into());
2739 ///
2740 /// // It shows up as an unknown component.
2741 /// let (cert, changed) = cert.insert_packets(unknown)?;
2742 /// assert!(changed);
2743 /// assert_eq!(cert.unknowns().count(), 1);
2744 /// for p in cert.unknowns() {
2745 /// assert_eq!(p.unknown().tag(), tag);
2746 /// }
2747 ///
2748 ///
2749 /// // Try and merge a literal data packet.
2750 /// let mut lit = Literal::new(DataFormat::Unicode);
2751 /// lit.set_body(b"test".to_vec());
2752 ///
2753 /// // Merging packets that are known to not belong to a
2754 /// // certificate result in an error.
2755 /// assert!(cert.insert_packets(lit).is_err());
2756 /// # Ok(())
2757 /// # }
2758 /// ```
2759 ///
2760 /// Remove secret key material:
2761 ///
2762 /// ```
2763 /// use sequoia_openpgp as openpgp;
2764 /// use openpgp::cert::prelude::*;
2765 /// use openpgp::packet::prelude::*;
2766 ///
2767 /// # fn main() -> openpgp::Result<()> {
2768 /// // Create a new key.
2769 /// let (cert, _) =
2770 /// CertBuilder::general_purpose(Some("alice@example.org"))
2771 /// .generate()?;
2772 /// assert!(cert.is_tsk());
2773 ///
2774 /// // We just created the key, so all the keys have secret key
2775 /// // material.
2776 /// let mut pk = cert.primary_key().key().clone();
2777 ///
2778 /// // Split off the secret key material.
2779 /// let (pk, sk) = pk.take_secret();
2780 /// assert!(sk.is_some());
2781 /// assert!(! pk.has_secret());
2782 ///
2783 /// // Merge in the public key. Recall: the packets that are
2784 /// // being merged into the certificate take precedence.
2785 /// let (cert, changed) = cert.insert_packets(pk)?;
2786 /// assert!(changed);
2787 ///
2788 /// // The secret key material is stripped.
2789 /// assert!(! cert.primary_key().key().has_secret());
2790 /// # Ok(())
2791 /// # }
2792 /// ```
2793 ///
2794 /// Update a binding signature's unhashed subpacket area:
2795 ///
2796 /// ```
2797 /// # fn main() -> sequoia_openpgp::Result<()> {
2798 /// use sequoia_openpgp as openpgp;
2799 /// use openpgp::cert::prelude::*;
2800 /// use openpgp::packet::prelude::*;
2801 /// use openpgp::packet::signature::subpacket::*;
2802 ///
2803 /// // Create a new key.
2804 /// let (cert, _) =
2805 /// CertBuilder::general_purpose(Some("alice@example.org"))
2806 /// .generate()?;
2807 /// assert_eq!(cert.userids().nth(0).unwrap().self_signatures().count(), 1);
2808 ///
2809 /// // Grab the binding signature so that we can modify it.
2810 /// let mut sig =
2811 /// cert.userids().nth(0).unwrap().self_signatures().nth(0)
2812 /// .unwrap().clone();
2813 ///
2814 /// // Add a notation subpacket. Note that the information is not
2815 /// // authenticated, therefore it may only be trusted if the
2816 /// // certificate with the signature is placed in a trusted store.
2817 /// let notation = NotationData::new("retrieved-from@example.org",
2818 /// "generated-locally",
2819 /// NotationDataFlags::empty()
2820 /// .set_human_readable());
2821 /// sig.unhashed_area_mut().add(
2822 /// Subpacket::new(SubpacketValue::NotationData(notation), false)?)?;
2823 ///
2824 /// // Merge in the signature. Recall: the packets that are
2825 /// // being merged into the certificate take precedence.
2826 /// let (cert, changed) = cert.insert_packets(sig)?;
2827 /// assert!(changed);
2828 ///
2829 /// // The old binding signature is replaced.
2830 /// assert_eq!(cert.userids().nth(0).unwrap().self_signatures().count(), 1);
2831 /// assert_eq!(cert.userids().nth(0).unwrap().self_signatures().nth(0)
2832 /// .unwrap()
2833 /// .unhashed_area()
2834 /// .subpackets(SubpacketTag::NotationData).count(), 1);
2835 /// # Ok(()) }
2836 /// ```
2837 pub fn insert_packets<I>(self, packets: I)
2838 -> Result<(Self, bool)>
2839 where I: IntoIterator,
2840 I::Item: Into<Packet>,
2841 {
2842 self.insert_packets_merge(packets, |_old, new| Ok(new))
2843 }
2844
2845 /// Adds packets to the certificate with an explicit merge policy.
2846 ///
2847 /// Like [`Cert::insert_packets`], but also takes a function that
2848 /// will be called on inserts and replacements that can be used to
2849 /// log changes to the certificate, and to influence how packets
2850 /// are merged. The merge function takes two parameters, an
2851 /// optional existing packet, and the packet to be merged in.
2852 ///
2853 /// If a new packet is inserted, there is no packet currently in
2854 /// the certificate. Hence, the first parameter to the merge
2855 /// function is `None`.
2856 ///
2857 /// If an existing packet is updated, there is a packet currently
2858 /// in the certificate that matches the given packet. Hence, the
2859 /// first parameter to the merge function is
2860 /// `Some(existing_packet)`.
2861 ///
2862 /// Both packets given to the merge function are considered equal
2863 /// when considering the normalized form (only comparing public
2864 /// key parameters and ignoring unhashed signature subpackets, see
2865 /// [`Packet::normalized_hash`]). It must return a packet that
2866 /// equals the input packet. In practice that means that the
2867 /// merge function returns either the old packet, the new packet,
2868 /// or a combination of both packets. If the merge function
2869 /// returns a different packet, this function returns
2870 /// [`Error::InvalidOperation`].
2871 ///
2872 /// If the merge function returns the existing packet, this
2873 /// function will still consider this as a change to the
2874 /// certificate. In other words, it may return that the
2875 /// certificate has changed even if the serialized representation
2876 /// has not changed.
2877 ///
2878 /// # Examples
2879 ///
2880 /// In the first example, we give an explicit merge function that
2881 /// just returns the new packet. This policy prefers the new
2882 /// packet. This is the policy used by [`Cert::insert_packets`].
2883 ///
2884 /// ```
2885 /// use sequoia_openpgp as openpgp;
2886 /// use openpgp::crypto::Password;
2887 /// use openpgp::cert::prelude::CertBuilder;
2888 ///
2889 /// # fn main() -> openpgp::Result<()> {
2890 /// let p0 = Password::from("old password");
2891 /// let p1 = Password::from("new password");
2892 ///
2893 /// // Create a new key.
2894 /// let (cert, rev) =
2895 /// CertBuilder::general_purpose(Some("alice@example.org"))
2896 /// .set_password(Some(p0.clone()))
2897 /// .generate()?;
2898 /// assert!(cert.is_tsk());
2899 ///
2900 /// // Change the password for the primary key.
2901 /// let pk = cert.primary_key().key().clone().parts_into_secret()?
2902 /// .decrypt_secret(&p0)?
2903 /// .encrypt_secret(&p1)?;
2904 ///
2905 /// // Merge it back in, with a policy projecting to the new packet.
2906 /// let (cert, changed) =
2907 /// cert.insert_packets_merge(pk, |_old, new| Ok(new))?;
2908 /// assert!(changed);
2909 ///
2910 /// // Make sure we can still decrypt the primary key using the
2911 /// // new password.
2912 /// assert!(cert.primary_key().key().clone().parts_into_secret()?
2913 /// .decrypt_secret(&p1).is_ok());
2914 /// # Ok(()) }
2915 /// ```
2916 ///
2917 /// In the second example, we give an explicit merge function that
2918 /// returns the old packet if given, falling back to the new
2919 /// packet, if not. This policy prefers the existing packets.
2920 ///
2921 /// ```
2922 /// use sequoia_openpgp as openpgp;
2923 /// use openpgp::crypto::Password;
2924 /// use openpgp::cert::prelude::CertBuilder;
2925 ///
2926 /// # fn main() -> openpgp::Result<()> {
2927 /// let p0 = Password::from("old password");
2928 /// let p1 = Password::from("new password");
2929 ///
2930 /// // Create a new key.
2931 /// let (cert, rev) =
2932 /// CertBuilder::general_purpose(Some("alice@example.org"))
2933 /// .set_password(Some(p0.clone()))
2934 /// .generate()?;
2935 /// assert!(cert.is_tsk());
2936 ///
2937 /// // Change the password for the primary key.
2938 /// let pk = cert.primary_key().key().clone().parts_into_secret()?
2939 /// .decrypt_secret(&p0)?
2940 /// .encrypt_secret(&p1)?;
2941 ///
2942 /// // Merge it back in, with a policy preferring the old packet.
2943 /// let (cert, changed) =
2944 /// cert.insert_packets_merge(pk, |old, new| Ok(old.unwrap_or(new)))?;
2945 /// assert!(changed); // Overestimates changes.
2946 ///
2947 /// // Make sure we can still decrypt the primary key using the
2948 /// // old password.
2949 /// assert!(cert.primary_key().key().clone().parts_into_secret()?
2950 /// .decrypt_secret(&p0).is_ok());
2951 /// # Ok(()) }
2952 /// ```
2953 pub fn insert_packets_merge<P, I>(self, packets: P, merge: I)
2954 -> Result<(Self, bool)>
2955 where P: IntoIterator,
2956 P::Item: Into<Packet>,
2957 I: FnMut(Option<Packet>, Packet) -> Result<Packet>,
2958 {
2959 self.insert_packets_(&mut packets.into_iter().map(Into::into),
2960 Box::new(merge))
2961 }
2962
2963 /// Adds packets to the certificate with an explicit merge policy.
2964 ///
2965 /// This implements all the Cert::insert_packets* functions. Its
2966 /// arguments `packets` and `merge` use dynamic dispatch so that
2967 /// we avoid the cost of monomorphization.
2968 fn insert_packets_<'a>(self,
2969 packets: &mut dyn Iterator<Item = Packet>,
2970 mut merge: Box<dyn FnMut(Option<Packet>, Packet)
2971 -> Result<Packet> + 'a>)
2972 -> Result<(Self, bool)>
2973 {
2974 let mut changed = false;
2975 let mut combined =
2976 self.as_tsk().into_packets().collect::<Vec<_>>();
2977
2978 // Hashes a packet ignoring the unhashed subpacket area and
2979 // any secret key material.
2980 let hash_packet = |p: &Packet| -> u64 {
2981 let mut hasher = DefaultHasher::new();
2982 p.normalized_hash(&mut hasher);
2983 hasher.finish()
2984 };
2985
2986 // BTreeMap of (hash) -> Vec<index in combined>.
2987 //
2988 // We don't use a HashMap, because the key would be a
2989 // reference to the packets in combined, which would prevent
2990 // us from modifying combined.
2991 //
2992 // Note: we really don't want to dedup components now, because
2993 // we want to keep signatures immediately after their
2994 // components.
2995 let mut packet_map: BTreeMap<u64, Vec<usize>> = BTreeMap::new();
2996 for (i, p) in combined.iter().enumerate() {
2997 match packet_map.entry(hash_packet(p)) {
2998 Entry::Occupied(mut oe) => {
2999 oe.get_mut().push(i)
3000 }
3001 Entry::Vacant(ve) => {
3002 ve.insert(vec![ i ]);
3003 }
3004 }
3005 }
3006
3007 enum Action {
3008 Drop,
3009 Overwrite(usize),
3010 Insert,
3011 }
3012 use Action::*;
3013
3014 // Now we merge in the new packets.
3015 for p in packets {
3016 Cert::valid_packet(&p)?;
3017
3018 let hash = hash_packet(&p);
3019 let mut action = Insert;
3020 if let Some(combined_i) = packet_map.get(&hash) {
3021 for i in combined_i {
3022 let i: usize = *i;
3023 let (same, identical) = match (&p, &combined[i]) {
3024 // For keys, only compare the public bits. If
3025 // they match, then we keep whatever is in the
3026 // new key.
3027 (Packet::PublicKey(a), Packet::PublicKey(b)) =>
3028 (a.public_cmp(b) == Ordering::Equal,
3029 a == b),
3030 (Packet::SecretKey(a), Packet::SecretKey(b)) =>
3031 (a.public_cmp(b) == Ordering::Equal,
3032 a == b),
3033 (Packet::PublicKey(a), Packet::SecretKey(b)) =>
3034 (a.public_cmp(b) == Ordering::Equal,
3035 false),
3036 (Packet::SecretKey(a), Packet::PublicKey(b)) =>
3037 (a.public_cmp(b) == Ordering::Equal,
3038 false),
3039
3040 (Packet::PublicSubkey(a), Packet::PublicSubkey(b)) =>
3041 (a.public_cmp(b) == Ordering::Equal,
3042 a == b),
3043 (Packet::SecretSubkey(a), Packet::SecretSubkey(b)) =>
3044 (a.public_cmp(b) == Ordering::Equal,
3045 a == b),
3046 (Packet::PublicSubkey(a), Packet::SecretSubkey(b)) =>
3047 (a.public_cmp(b) == Ordering::Equal,
3048 false),
3049 (Packet::SecretSubkey(a), Packet::PublicSubkey(b)) =>
3050 (a.public_cmp(b) == Ordering::Equal,
3051 false),
3052
3053 // For signatures, don't compare the unhashed
3054 // subpacket areas. If it's the same
3055 // signature, then we keep what is the new
3056 // signature's unhashed subpacket area.
3057 (Packet::Signature(a), Packet::Signature(b)) =>
3058 (a.normalized_eq(b),
3059 a == b),
3060
3061 (a, b) => {
3062 let identical = a == b;
3063 (identical, identical)
3064 }
3065 };
3066
3067 if same {
3068 if identical {
3069 action = Drop;
3070 } else {
3071 action = Overwrite(i);
3072 }
3073 break;
3074 }
3075 }
3076 }
3077
3078 match action {
3079 Drop => (),
3080 Overwrite(i) => {
3081 // Existing packet.
3082 let existing =
3083 std::mem::replace(&mut combined[i],
3084 Packet::Marker(Default::default()));
3085 let merged = merge(Some(existing), p)?;
3086 let merged_hash = hash_packet(&merged);
3087 if hash != merged_hash {
3088 return Err(Error::InvalidOperation(
3089 format!("merge function changed packet hash \
3090 (expected: {}, got: {})",
3091 hash, merged_hash)).into());
3092 }
3093
3094 combined[i] = merged;
3095 changed = true;
3096 },
3097 Insert => {
3098 // New packet.
3099 let merged = merge(None, p)?;
3100 let merged_hash = hash_packet(&merged);
3101 if hash != merged_hash {
3102 return Err(Error::InvalidOperation(
3103 format!("merge function changed packet hash \
3104 (expected: {}, got: {})",
3105 hash, merged_hash)).into());
3106 }
3107
3108 // Add it to combined.
3109 combined.push(merged);
3110 changed = true;
3111
3112 // Because the caller might insert the same packet
3113 // multiple times, we need to also add it to
3114 // packet_map.
3115 let i = combined.len() - 1;
3116 match packet_map.entry(hash) {
3117 Entry::Occupied(mut oe) => {
3118 oe.get_mut().push(i)
3119 }
3120 Entry::Vacant(ve) => {
3121 ve.insert(vec![ i ]);
3122 }
3123 }
3124 }
3125 }
3126 }
3127
3128 Cert::try_from(combined).map(|cert| (cert, changed))
3129 }
3130
3131 /// Returns whether at least one of the keys includes secret
3132 /// key material.
3133 ///
3134 /// This returns true if either the primary key or at least one of
3135 /// the subkeys includes secret key material.
3136 ///
3137 /// # Examples
3138 ///
3139 /// ```
3140 /// use sequoia_openpgp as openpgp;
3141 /// use openpgp::cert::prelude::*;
3142 /// use openpgp::policy::StandardPolicy;
3143 /// use openpgp::serialize::Serialize;
3144 /// use openpgp::parse::Parse;
3145 ///
3146 /// # fn main() -> openpgp::Result<()> {
3147 /// let p = &StandardPolicy::new();
3148 ///
3149 /// // Create a new key.
3150 /// let (cert, _) =
3151 /// CertBuilder::general_purpose(Some("alice@example.org"))
3152 /// .generate()?;
3153 /// assert!(cert.is_tsk());
3154 ///
3155 /// // If we serialize the certificate, the secret key material is
3156 /// // stripped, unless we first convert it to a TSK.
3157 ///
3158 /// let mut buffer = Vec::new();
3159 /// cert.as_tsk().serialize(&mut buffer);
3160 /// let cert = Cert::from_bytes(&buffer)?;
3161 /// assert!(cert.is_tsk());
3162 ///
3163 /// // Now round trip it without first converting it to a TSK. This
3164 /// // drops the secret key material.
3165 /// let mut buffer = Vec::new();
3166 /// cert.serialize(&mut buffer);
3167 /// let cert = Cert::from_bytes(&buffer)?;
3168 /// assert!(!cert.is_tsk());
3169 /// # Ok(())
3170 /// # }
3171 /// ```
3172 pub fn is_tsk(&self) -> bool {
3173 if self.primary_key().has_secret() {
3174 return true;
3175 }
3176 self.keys().subkeys().any(|sk| {
3177 sk.key().has_secret()
3178 })
3179 }
3180
3181 /// Strips any secret key material.
3182 ///
3183 /// # Examples
3184 ///
3185 /// ```
3186 /// use sequoia_openpgp as openpgp;
3187 /// use openpgp::cert::prelude::*;
3188 ///
3189 /// # fn main() -> openpgp::Result<()> {
3190 ///
3191 /// // Create a new key.
3192 /// let (cert, _) =
3193 /// CertBuilder::general_purpose(Some("alice@example.org"))
3194 /// .generate()?;
3195 /// assert!(cert.is_tsk());
3196 ///
3197 /// let cert = cert.strip_secret_key_material();
3198 /// assert!(! cert.is_tsk());
3199 /// # Ok(())
3200 /// # }
3201 /// ```
3202 pub fn strip_secret_key_material(mut self) -> Cert {
3203 self.primary.key_mut().steal_secret();
3204 self.subkeys.iter_mut().for_each(|sk| {
3205 sk.key_mut().steal_secret();
3206 });
3207 self
3208 }
3209
3210 /// Retains only the userids specified by the predicate.
3211 ///
3212 /// Removes all the userids for which the given predicate returns
3213 /// false.
3214 ///
3215 /// # Warning
3216 ///
3217 /// Because userid binding signatures are traditionally used to
3218 /// provide additional information like the certificate holder's
3219 /// algorithm preferences (see [`Preferences`]) and primary key
3220 /// flags (see [`ValidKeyAmalgamation::key_flags`]). Removing a
3221 /// userid may inadvertently change this information.
3222 ///
3223 /// [`ValidKeyAmalgamation::key_flags`]: amalgamation::key::ValidKeyAmalgamation::key_flags()
3224 ///
3225 /// # Examples
3226 ///
3227 /// ```
3228 /// # fn main() -> sequoia_openpgp::Result<()> {
3229 /// use sequoia_openpgp as openpgp;
3230 /// use openpgp::cert::prelude::*;
3231 ///
3232 /// // Create a new key.
3233 /// let (cert, _) =
3234 /// CertBuilder::general_purpose(Some("alice@example.org"))
3235 /// .add_userid("Alice Lovelace <alice@lovelace.name>")
3236 /// .generate()?;
3237 /// assert_eq!(cert.userids().count(), 2);
3238 ///
3239 /// let cert = cert.retain_userids(|ua| {
3240 /// if let Ok(Some(address)) = ua.userid().email() {
3241 /// address == "alice@example.org" // Only keep this one.
3242 /// } else {
3243 /// false // Drop malformed userids.
3244 /// }
3245 /// });
3246 /// assert_eq!(cert.userids().count(), 1);
3247 /// assert_eq!(cert.userids().nth(0).unwrap().userid().email()?.unwrap(),
3248 /// "alice@example.org");
3249 /// # Ok(()) }
3250 /// ```
3251 pub fn retain_userids<P>(mut self, mut predicate: P) -> Cert
3252 where P: FnMut(UserIDAmalgamation) -> bool,
3253 {
3254 let mut keep = vec![false; self.userids.len()];
3255 for (i, a) in self.userids().enumerate() {
3256 keep[i] = predicate(a);
3257 }
3258 // Note: Vec::retain visits the elements in the original
3259 // order.
3260 let mut keep = keep.iter();
3261 self.userids.retain(|_| *keep.next().unwrap());
3262 self
3263 }
3264
3265 /// Retains only the user attributes specified by the predicate.
3266 ///
3267 /// Removes all the user attributes for which the given predicate
3268 /// returns false.
3269 ///
3270 /// # Examples
3271 ///
3272 /// ```
3273 /// # fn main() -> sequoia_openpgp::Result<()> {
3274 /// use sequoia_openpgp as openpgp;
3275 /// use openpgp::cert::prelude::*;
3276 ///
3277 /// // Create a new key.
3278 /// let (cert, _) =
3279 /// CertBuilder::general_purpose(Some("alice@example.org"))
3280 /// // Add nonsensical user attribute.
3281 /// .add_user_attribute(vec![0, 1, 2])
3282 /// .generate()?;
3283 /// assert_eq!(cert.user_attributes().count(), 1);
3284 ///
3285 /// // Strip all user attributes
3286 /// let cert = cert.retain_user_attributes(|_| false);
3287 /// assert_eq!(cert.user_attributes().count(), 0);
3288 /// # Ok(()) }
3289 /// ```
3290 pub fn retain_user_attributes<P>(mut self, mut predicate: P) -> Cert
3291 where P: FnMut(UserAttributeAmalgamation) -> bool,
3292 {
3293 let mut keep = vec![false; self.user_attributes.len()];
3294 for (i, a) in self.user_attributes().enumerate() {
3295 keep[i] = predicate(a);
3296 }
3297 // Note: Vec::retain visits the elements in the original
3298 // order.
3299 let mut keep = keep.iter();
3300 self.user_attributes.retain(|_| *keep.next().unwrap());
3301 self
3302 }
3303
3304 /// Retains only the subkeys specified by the predicate.
3305 ///
3306 /// Removes all the subkeys for which the given predicate returns
3307 /// false.
3308 ///
3309 /// # Examples
3310 ///
3311 /// ```
3312 /// # fn main() -> sequoia_openpgp::Result<()> {
3313 /// use sequoia_openpgp as openpgp;
3314 /// use openpgp::policy::StandardPolicy;
3315 /// use openpgp::cert::prelude::*;
3316 ///
3317 /// // Create a new key.
3318 /// let (cert, _) =
3319 /// CertBuilder::new()
3320 /// .add_userid("Alice Lovelace <alice@lovelace.name>")
3321 /// .add_transport_encryption_subkey()
3322 /// .add_storage_encryption_subkey()
3323 /// .generate()?;
3324 /// assert_eq!(cert.keys().subkeys().count(), 2);
3325 ///
3326 /// // Retain only the transport encryption subkey. For that, we
3327 /// // need to examine the key flags, therefore we need to turn
3328 /// // the `KeyAmalgamation` into a `ValidKeyAmalgamation` under a
3329 /// // policy.
3330 /// let p = &StandardPolicy::new();
3331 /// let cert = cert.retain_subkeys(|ka| {
3332 /// if let Ok(vka) = ka.with_policy(p, None) {
3333 /// vka.key_flags().map(|flags| flags.for_transport_encryption())
3334 /// .unwrap_or(false) // Keep transport encryption keys.
3335 /// } else {
3336 /// false // Drop unbound keys.
3337 /// }
3338 /// });
3339 /// assert_eq!(cert.keys().subkeys().count(), 1);
3340 /// assert!(cert.with_policy(p, None)?.keys().subkeys().nth(0).unwrap()
3341 /// .key_flags().unwrap().for_transport_encryption());
3342 /// # Ok(()) }
3343 /// ```
3344 pub fn retain_subkeys<P>(mut self, mut predicate: P) -> Cert
3345 where P: FnMut(SubordinateKeyAmalgamation<crate::packet::key::PublicParts>) -> bool,
3346 {
3347 let mut keep = vec![false; self.subkeys.len()];
3348 for (i, a) in self.keys().subkeys().enumerate() {
3349 keep[i] = predicate(a);
3350 }
3351 // Note: Vec::retain visits the elements in the original
3352 // order.
3353 let mut keep = keep.iter();
3354 self.subkeys.retain(|_| *keep.next().unwrap());
3355 self
3356 }
3357
3358 /// Associates a policy and a reference time with the certificate.
3359 ///
3360 /// This is used to turn a `Cert` into a
3361 /// [`ValidCert`]. (See also [`ValidateAmalgamation`],
3362 /// which does the same for component amalgamations.)
3363 ///
3364 /// A certificate is considered valid if:
3365 ///
3366 /// - It has a self signature that is live at time `t`.
3367 ///
3368 /// - The policy considers it acceptable.
3369 ///
3370 /// This doesn't say anything about whether the certificate itself
3371 /// is alive (see [`ValidCert::alive`]) or revoked (see
3372 /// [`ValidCert::revocation_status`]).
3373 ///
3374 /// [`ValidateAmalgamation`]: amalgamation::ValidateAmalgamation
3375 /// [`ValidCert::alive`]: ValidCert::alive()
3376 /// [`ValidCert::revocation_status`]: ValidCert::revocation_status()
3377 ///
3378 /// # Examples
3379 ///
3380 /// ```
3381 /// use sequoia_openpgp as openpgp;
3382 /// # use openpgp::cert::prelude::*;
3383 /// use openpgp::policy::StandardPolicy;
3384 ///
3385 /// # fn main() -> openpgp::Result<()> {
3386 /// let p = &StandardPolicy::new();
3387 ///
3388 /// # let (cert, _) =
3389 /// # CertBuilder::general_purpose(Some("alice@example.org"))
3390 /// # .generate()?;
3391 /// let vc = cert.with_policy(p, None)?;
3392 /// # assert!(std::ptr::eq(vc.policy(), p));
3393 /// # Ok(())
3394 /// # }
3395 /// ```
3396 pub fn with_policy<'a, T>(&'a self, policy: &'a dyn Policy, time: T)
3397 -> Result<ValidCert<'a>>
3398 where T: Into<Option<time::SystemTime>>,
3399 {
3400 let time = time.into().unwrap_or_else(crate::now);
3401 self.primary_key().with_policy(policy, time)?;
3402
3403 Ok(ValidCert {
3404 cert: self,
3405 policy,
3406 time,
3407 })
3408 }
3409}
3410
3411use crate::serialize::TSK;
3412impl<'a> TSK<'a> {
3413 /// Converts the certificate into an iterator over a sequence of
3414 /// packets.
3415 ///
3416 /// This function emits secret key packets, modulo the keys that
3417 /// are filtered (see [`TSK::set_filter`]). If requested, missing
3418 /// secret key material is replaced by stubs (see
3419 /// [`TSK::emit_secret_key_stubs`]).
3420 ///
3421 /// # Examples
3422 ///
3423 /// ```
3424 /// # use sequoia_openpgp as openpgp;
3425 /// # use openpgp::cert::prelude::*;
3426 /// # use openpgp::serialize::{Serialize, SerializeInto};
3427 /// #
3428 /// # fn main() -> openpgp::Result<()> {
3429 /// # let (cert, _) =
3430 /// # CertBuilder::general_purpose(Some("alice@example.org"))
3431 /// # .generate()?;
3432 /// assert!(cert.is_tsk());
3433 /// let a = cert.as_tsk().to_vec()?;
3434 /// let mut b = Vec::new();
3435 /// cert.into_tsk().into_packets()
3436 /// .for_each(|p| p.serialize(&mut b).unwrap());
3437 /// assert_eq!(a, b);
3438 /// # Ok(()) }
3439 /// ```
3440 pub fn into_packets(self) -> impl Iterator<Item=Packet> + Send + Sync + 'a {
3441 /// Strips the secret key material if the filter rejects it,
3442 /// and optionally inserts secret key stubs.
3443 fn rewrite<'a>(
3444 filter: &Box<dyn Fn(&key::UnspecifiedSecret) -> bool + Send + Sync + 'a>,
3445 emit_secret_key_stubs: bool,
3446 mut p: impl Iterator<Item=Packet> + Send + Sync)
3447 -> impl Iterator<Item=Packet> + Send + Sync
3448 {
3449 let k: Packet = match p.next().unwrap() {
3450 Packet::PublicKey(mut k) => {
3451 if ! k.role_as_unspecified().parts_as_secret()
3452 .map(|k| (filter)(k))
3453 .unwrap_or(false)
3454 {
3455 k = k.take_secret().0;
3456 }
3457
3458 if ! k.has_secret() && emit_secret_key_stubs {
3459 k = TSK::add_stub(k).into();
3460 }
3461
3462 if k.has_secret() {
3463 Packet::SecretKey(k.parts_into_secret().unwrap())
3464 } else {
3465 Packet::PublicKey(k)
3466 }
3467 }
3468 Packet::PublicSubkey(mut k) => {
3469 if ! k.role_as_unspecified().parts_as_secret()
3470 .map(|k| (filter)(k))
3471 .unwrap_or(false)
3472 {
3473 k = k.take_secret().0;
3474 }
3475
3476 if ! k.has_secret() && emit_secret_key_stubs {
3477 k = TSK::add_stub(k).into();
3478 }
3479
3480 if k.has_secret() {
3481 Packet::SecretSubkey(k.parts_into_secret().unwrap())
3482 } else {
3483 Packet::PublicSubkey(k)
3484 }
3485 }
3486 _ => unreachable!(),
3487 };
3488
3489 std::iter::once(k).chain(p)
3490 }
3491
3492 let (cert, filter, emit_secret_key_stubs) = self.decompose();
3493 let cert = cert.into_owned();
3494
3495 rewrite(&filter, emit_secret_key_stubs, cert.primary.into_packets())
3496 .chain(cert.userids.into_iter().flat_map(|b| b.into_packets()))
3497 .chain(cert.user_attributes.into_iter().flat_map(|b| b.into_packets()))
3498 .chain(cert.subkeys.into_iter().flat_map(
3499 move |b| rewrite(&filter, emit_secret_key_stubs, b.into_packets())))
3500 .chain(cert.unknowns.into_iter().flat_map(|b| b.into_packets()))
3501 .chain(cert.bad.into_iter().map(|s| s.into()))
3502 }
3503}
3504
3505impl TryFrom<PacketParserResult<'_>> for Cert {
3506 type Error = anyhow::Error;
3507
3508 /// Returns the Cert found in the packet stream.
3509 ///
3510 /// If the sequence contains multiple certificates (i.e., it is a
3511 /// keyring), or the certificate is followed by an invalid packet
3512 /// this function will fail. To parse keyrings, use
3513 /// [`CertParser`] instead of this function.
3514 fn try_from(ppr: PacketParserResult) -> Result<Self> {
3515 let mut parser = parser::CertParser::from(ppr);
3516 if let Some(cert_result) = parser.next() {
3517 if parser.next().is_some() {
3518 Err(Error::MalformedCert(
3519 "Additional packets found, is this a keyring?".into()
3520 ).into())
3521 } else {
3522 cert_result
3523 }
3524 } else {
3525 Err(Error::MalformedCert("No data".into()).into())
3526 }
3527 }
3528}
3529
3530impl TryFrom<Vec<Packet>> for Cert {
3531 type Error = anyhow::Error;
3532
3533 fn try_from(p: Vec<Packet>) -> Result<Self> {
3534 Cert::from_packets(p.into_iter())
3535 }
3536}
3537
3538impl TryFrom<Packet> for Cert {
3539 type Error = anyhow::Error;
3540
3541 fn try_from(p: Packet) -> Result<Self> {
3542 Cert::from_packets(std::iter::once(p))
3543 }
3544}
3545
3546impl TryFrom<PacketPile> for Cert {
3547 type Error = anyhow::Error;
3548
3549 /// Returns the certificate found in the `PacketPile`.
3550 ///
3551 /// If the [`PacketPile`] does not start with a certificate
3552 /// (specifically, if it does not start with a primary key
3553 /// packet), then this fails.
3554 ///
3555 /// If the sequence contains multiple certificates (i.e., it is a
3556 /// keyring), or the certificate is followed by an invalid packet
3557 /// this function will fail. To parse keyrings, use
3558 /// [`CertParser`] instead of this function.
3559 ///
3560 /// # Examples
3561 ///
3562 /// ```
3563 /// use sequoia_openpgp as openpgp;
3564 /// use openpgp::cert::prelude::*;
3565 /// use openpgp::packet::prelude::*;
3566 /// use openpgp::PacketPile;
3567 /// use std::convert::TryFrom;
3568 ///
3569 /// # fn main() -> openpgp::Result<()> {
3570 /// let (cert, rev) =
3571 /// CertBuilder::general_purpose(Some("alice@example.org"))
3572 /// .generate()?;
3573 ///
3574 /// // We should be able to turn a certificate into a PacketPile
3575 /// // and back.
3576 /// let pp : PacketPile = cert.into();
3577 /// assert!(Cert::try_from(pp).is_ok());
3578 ///
3579 /// // But a revocation certificate is not a certificate, so this
3580 /// // will fail.
3581 /// let pp : PacketPile = Packet::from(rev).into();
3582 /// assert!(Cert::try_from(pp).is_err());
3583 /// # Ok(())
3584 /// # }
3585 /// ```
3586 fn try_from(p: PacketPile) -> Result<Self> {
3587 Self::from_packets(p.into_children())
3588 }
3589}
3590
3591/// A `Cert` plus a `Policy` and a reference time.
3592///
3593/// A `ValidCert` combines a [`Cert`] with a [`Policy`] and a
3594/// reference time. This allows it to implement methods that require
3595/// a `Policy` and a reference time without requiring the caller to
3596/// explicitly pass them in. Embedding them in the `ValidCert` data
3597/// structure rather than having the caller pass them in explicitly
3598/// helps ensure that multipart operations, even those that span
3599/// multiple functions, use the same `Policy` and reference time.
3600/// This avoids a subtle class of bugs in which different views of a
3601/// certificate are unintentionally used.
3602///
3603/// A `ValidCert` is typically obtained by transforming a `Cert` using
3604/// [`Cert::with_policy`].
3605///
3606/// A `ValidCert` is guaranteed to have a valid and live binding
3607/// signature at the specified reference time. Note: this only means
3608/// that the binding signature is live; it says nothing about whether
3609/// the certificate or any component is live. If you care about those
3610/// things, then you need to check them separately.
3611///
3612/// [`Policy`]: crate::policy::Policy
3613/// [`Cert::with_policy`]: Cert::with_policy()
3614///
3615/// # Examples
3616///
3617/// ```
3618/// use sequoia_openpgp as openpgp;
3619/// # use openpgp::cert::prelude::*;
3620/// use openpgp::policy::StandardPolicy;
3621///
3622/// # fn main() -> openpgp::Result<()> {
3623/// let p = &StandardPolicy::new();
3624///
3625/// # let (cert, _) = CertBuilder::new()
3626/// # .add_userid("Alice")
3627/// # .add_signing_subkey()
3628/// # .add_transport_encryption_subkey()
3629/// # .generate()?;
3630/// let vc = cert.with_policy(p, None)?;
3631/// # assert!(std::ptr::eq(vc.policy(), p));
3632/// # Ok(()) }
3633/// ```
3634#[derive(Debug, Clone)]
3635pub struct ValidCert<'a> {
3636 cert: &'a Cert,
3637 policy: &'a dyn Policy,
3638 // The reference time.
3639 time: time::SystemTime,
3640}
3641assert_send_and_sync!(ValidCert<'_>);
3642
3643impl<'a> fmt::Display for ValidCert<'a> {
3644 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3645 write!(f, "{}", self.cert().fingerprint())
3646 }
3647}
3648
3649impl<'a> ValidCert<'a> {
3650 /// Returns the underlying certificate.
3651 ///
3652 /// # Examples
3653 ///
3654 /// ```
3655 /// use sequoia_openpgp as openpgp;
3656 /// # use openpgp::cert::prelude::*;
3657 /// use openpgp::policy::StandardPolicy;
3658 ///
3659 /// # fn main() -> openpgp::Result<()> {
3660 /// let p = &StandardPolicy::new();
3661 ///
3662 /// # let (cert, _) = CertBuilder::new()
3663 /// # .add_userid("Alice")
3664 /// # .add_signing_subkey()
3665 /// # .add_transport_encryption_subkey()
3666 /// # .generate()?;
3667 /// let vc = cert.with_policy(p, None)?;
3668 /// assert!(std::ptr::eq(vc.cert(), &cert));
3669 /// # assert!(std::ptr::eq(vc.policy(), p));
3670 /// # Ok(()) }
3671 /// ```
3672 pub fn cert(&self) -> &'a Cert {
3673 self.cert
3674 }
3675
3676 /// Returns the associated reference time.
3677 ///
3678 /// # Examples
3679 ///
3680 /// ```
3681 /// # use std::time::{SystemTime, Duration, UNIX_EPOCH};
3682 /// #
3683 /// use sequoia_openpgp as openpgp;
3684 /// # use openpgp::cert::prelude::*;
3685 /// use openpgp::policy::StandardPolicy;
3686 ///
3687 /// # fn main() -> openpgp::Result<()> {
3688 /// let p = &StandardPolicy::new();
3689 ///
3690 /// let t = UNIX_EPOCH + Duration::from_secs(1307732220);
3691 /// # let (cert, _) =
3692 /// # CertBuilder::general_purpose(Some("alice@example.org"))
3693 /// # .set_creation_time(t)
3694 /// # .generate()?;
3695 /// let vc = cert.with_policy(p, t)?;
3696 /// assert_eq!(vc.time(), t);
3697 /// # Ok(())
3698 /// # }
3699 /// ```
3700 pub fn time(&self) -> time::SystemTime {
3701 self.time
3702 }
3703
3704 /// Returns the associated policy.
3705 ///
3706 /// # Examples
3707 ///
3708 /// ```
3709 /// use sequoia_openpgp as openpgp;
3710 /// # use openpgp::cert::prelude::*;
3711 /// use openpgp::policy::StandardPolicy;
3712 ///
3713 /// # fn main() -> openpgp::Result<()> {
3714 /// let p = &StandardPolicy::new();
3715 ///
3716 /// # let (cert, _) =
3717 /// # CertBuilder::general_purpose(Some("alice@example.org"))
3718 /// # .generate()?;
3719 /// let vc = cert.with_policy(p, None)?;
3720 /// assert!(std::ptr::eq(vc.policy(), p));
3721 /// # Ok(())
3722 /// # }
3723 /// ```
3724 pub fn policy(&self) -> &'a dyn Policy {
3725 self.policy
3726 }
3727
3728 /// Changes the associated policy and reference time.
3729 ///
3730 /// If `time` is `None`, the current time is used.
3731 ///
3732 /// Returns an error if the certificate is not valid for the given
3733 /// policy at the specified time.
3734 ///
3735 /// # Examples
3736 ///
3737 /// ```
3738 /// use sequoia_openpgp as openpgp;
3739 /// # use openpgp::cert::prelude::*;
3740 /// use openpgp::policy::{StandardPolicy, NullPolicy};
3741 ///
3742 /// # fn main() -> openpgp::Result<()> {
3743 /// # let (cert, _) =
3744 /// # CertBuilder::general_purpose(Some("alice@example.org"))
3745 /// # .generate()?;
3746 /// let sp = &StandardPolicy::new();
3747 /// let vc = cert.with_policy(sp, None)?;
3748 ///
3749 /// // ...
3750 ///
3751 /// // Now with a different policy.
3752 /// let np = unsafe { &NullPolicy::new() };
3753 /// let vc = vc.with_policy(np, None)?;
3754 /// # Ok(())
3755 /// # }
3756 /// ```
3757 pub fn with_policy<T>(self, policy: &'a dyn Policy, time: T)
3758 -> Result<ValidCert<'a>>
3759 where T: Into<Option<time::SystemTime>>,
3760 {
3761 self.cert.with_policy(policy, time)
3762 }
3763
3764 /// Returns the certificate's direct key signature as of the
3765 /// reference time.
3766 ///
3767 /// Subpackets on direct key signatures apply to all components of
3768 /// the certificate, cf. [Section 5.2.3.10 of RFC 9580].
3769 ///
3770 /// [Section 5.2.3.10 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.10
3771 ///
3772 /// # Examples
3773 ///
3774 /// ```
3775 /// use sequoia_openpgp as openpgp;
3776 /// # use openpgp::cert::prelude::*;
3777 /// use sequoia_openpgp::policy::StandardPolicy;
3778 ///
3779 /// # fn main() -> openpgp::Result<()> {
3780 /// let p = &StandardPolicy::new();
3781 ///
3782 /// # let (cert, _) = CertBuilder::new()
3783 /// # .add_userid("Alice")
3784 /// # .add_signing_subkey()
3785 /// # .add_transport_encryption_subkey()
3786 /// # .generate()?;
3787 /// let vc = cert.with_policy(p, None)?;
3788 /// println!("{:?}", vc.direct_key_signature());
3789 /// # assert!(vc.direct_key_signature().is_ok());
3790 /// # Ok(()) }
3791 /// ```
3792 pub fn direct_key_signature(&self) -> Result<&'a Signature>
3793 {
3794 self.cert.primary.binding_signature(self.policy(), self.time())
3795 }
3796
3797 /// Returns the certificate's revocation status.
3798 ///
3799 /// A certificate is considered revoked at time `t` if:
3800 ///
3801 /// - There is a valid and live revocation at time `t` that is
3802 /// newer than all valid and live self signatures at time `t`,
3803 /// or
3804 ///
3805 /// - There is a valid [hard revocation] (even if it is not live
3806 /// at time `t`, and even if there is a newer self signature).
3807 ///
3808 /// [hard revocation]: crate::types::RevocationType::Hard
3809 ///
3810 /// Note: certificates and subkeys have different revocation
3811 /// criteria from [User IDs] and [User Attributes].
3812 ///
3813 // Pending https://github.com/rust-lang/rust/issues/85960, should be
3814 // [User IDs]: bundle::ComponentBundle<UserID>::revocation_status
3815 // [User Attributes]: bundle::ComponentBundle<UserAttribute>::revocation_status
3816 /// [User IDs]: bundle::ComponentBundle#method.revocation_status-1
3817 /// [User Attributes]: bundle::ComponentBundle#method.revocation_status-2
3818 ///
3819 /// # Examples
3820 ///
3821 /// ```
3822 /// use sequoia_openpgp as openpgp;
3823 /// use openpgp::cert::prelude::*;
3824 /// use openpgp::types::RevocationStatus;
3825 /// use openpgp::policy::StandardPolicy;
3826 ///
3827 /// # fn main() -> openpgp::Result<()> {
3828 /// let p = &StandardPolicy::new();
3829 ///
3830 /// let (cert, rev) =
3831 /// CertBuilder::general_purpose(Some("alice@example.org"))
3832 /// .generate()?;
3833 ///
3834 /// // Not revoked.
3835 /// assert_eq!(cert.with_policy(p, None)?.revocation_status(),
3836 /// RevocationStatus::NotAsFarAsWeKnow);
3837 ///
3838 /// // Merge the revocation certificate. `cert` is now considered
3839 /// // to be revoked.
3840 /// let cert = cert.insert_packets(rev.clone())?.0;
3841 /// assert_eq!(cert.with_policy(p, None)?.revocation_status(),
3842 /// RevocationStatus::Revoked(vec![&rev.into()]));
3843 /// # Ok(())
3844 /// # }
3845 /// ```
3846 pub fn revocation_status(&self) -> RevocationStatus<'a> {
3847 self.cert.revocation_status(self.policy, self.time)
3848 }
3849
3850 /// Returns whether the certificate is alive at the
3851 /// reference time.
3852 ///
3853 /// A certificate is considered to be alive at time `t` if the
3854 /// primary key is alive at time `t`.
3855 ///
3856 /// A valid certificate's primary key is guaranteed to have [a live
3857 /// binding signature], however, that does not mean that the
3858 /// [primary key is necessarily alive].
3859 ///
3860 /// [a live binding signature]: amalgamation::ValidateAmalgamation
3861 /// [primary key is necessarily alive]: amalgamation::key::ValidKeyAmalgamation::alive()
3862 ///
3863 /// # Examples
3864 ///
3865 /// ```
3866 /// use std::time;
3867 /// use sequoia_openpgp as openpgp;
3868 /// use openpgp::cert::prelude::*;
3869 /// use openpgp::policy::StandardPolicy;
3870 ///
3871 /// # fn main() -> openpgp::Result<()> {
3872 /// let p = &StandardPolicy::new();
3873 ///
3874 /// let a_second = time::Duration::from_secs(1);
3875 ///
3876 /// let creation_time = time::SystemTime::now();
3877 /// let before_creation = creation_time - a_second;
3878 /// let validity_period = 60 * a_second;
3879 /// let expiration_time = creation_time + validity_period;
3880 /// let before_expiration_time = expiration_time - a_second;
3881 /// let after_expiration_time = expiration_time + a_second;
3882 ///
3883 /// let (cert, _) = CertBuilder::new()
3884 /// .add_userid("Alice")
3885 /// .set_creation_time(creation_time)
3886 /// .set_validity_period(validity_period)
3887 /// .generate()?;
3888 ///
3889 /// // There is no binding signature before the certificate was created.
3890 /// assert!(cert.with_policy(p, before_creation).is_err());
3891 /// assert!(cert.with_policy(p, creation_time)?.alive().is_ok());
3892 /// assert!(cert.with_policy(p, before_expiration_time)?.alive().is_ok());
3893 /// // The binding signature is still alive, but the key has expired.
3894 /// assert!(cert.with_policy(p, expiration_time)?.alive().is_err());
3895 /// assert!(cert.with_policy(p, after_expiration_time)?.alive().is_err());
3896 /// # Ok(()) }
3897 pub fn alive(&self) -> Result<()> {
3898 self.primary_key().alive()
3899 }
3900
3901 /// Returns the certificate's primary key.
3902 ///
3903 /// A key's secret key material may be protected with a
3904 /// password. In such cases, it needs to be decrypted before it
3905 /// can be used to decrypt data or generate a signature. Refer to
3906 /// [`Key::decrypt_secret`] for details.
3907 ///
3908 /// [`Key::decrypt_secret`]: crate::packet::Key::decrypt_secret()
3909 ///
3910 /// # Examples
3911 ///
3912 /// ```
3913 /// # use sequoia_openpgp as openpgp;
3914 /// # use openpgp::cert::prelude::*;
3915 /// # use openpgp::policy::StandardPolicy;
3916 /// #
3917 /// # fn main() -> openpgp::Result<()> {
3918 /// # let p = &StandardPolicy::new();
3919 /// # let (cert, _) = CertBuilder::new()
3920 /// # .add_userid("Alice")
3921 /// # .generate()?;
3922 /// # let vc = cert.with_policy(p, None)?;
3923 /// #
3924 /// let primary = vc.primary_key();
3925 /// // The certificate's fingerprint *is* the primary key's fingerprint.
3926 /// assert_eq!(vc.cert().fingerprint(), primary.key().fingerprint());
3927 /// # Ok(()) }
3928 pub fn primary_key(&self)
3929 -> ValidPrimaryKeyAmalgamation<'a, key::PublicParts>
3930 {
3931 self.cert.primary_key().with_policy(self.policy, self.time)
3932 .expect("A ValidKeyAmalgamation must have a ValidPrimaryKeyAmalgamation")
3933 }
3934
3935 /// Returns an iterator over the certificate's valid keys.
3936 ///
3937 /// That is, this returns an iterator over the primary key and any
3938 /// subkeys.
3939 ///
3940 /// The iterator always returns the primary key first. The order
3941 /// of the subkeys is undefined.
3942 ///
3943 /// To only iterate over the certificate's subkeys, call
3944 /// [`ValidKeyAmalgamationIter::subkeys`] on the returned iterator
3945 /// instead of skipping the first key: this causes the iterator to
3946 /// return values with a more accurate type.
3947 ///
3948 /// A key's secret key material may be protected with a
3949 /// password. In such cases, it needs to be decrypted before it
3950 /// can be used to decrypt data or generate a signature. Refer to
3951 /// [`Key::decrypt_secret`] for details.
3952 ///
3953 /// [`ValidKeyAmalgamationIter::subkeys`]: amalgamation::key::ValidKeyAmalgamationIter::subkeys()
3954 /// [`Key::decrypt_secret`]: crate::packet::Key::decrypt_secret()
3955 ///
3956 /// # Examples
3957 ///
3958 /// ```
3959 /// use sequoia_openpgp as openpgp;
3960 /// use openpgp::cert::prelude::*;
3961 /// use openpgp::policy::StandardPolicy;
3962 ///
3963 /// # fn main() -> openpgp::Result<()> {
3964 /// let p = &StandardPolicy::new();
3965 ///
3966 /// // Create a key with two subkeys: one for signing and one for
3967 /// // encrypting data in transit.
3968 /// let (cert, _) = CertBuilder::new()
3969 /// .add_userid("Alice")
3970 /// .add_signing_subkey()
3971 /// .add_transport_encryption_subkey()
3972 /// .generate()?;
3973 /// // They should all be valid.
3974 /// assert_eq!(cert.with_policy(p, None)?.keys().count(), 1 + 2);
3975 /// # Ok(())
3976 /// # }
3977 /// ```
3978 pub fn keys(&self) -> ValidKeyAmalgamationIter<'a, key::PublicParts, key::UnspecifiedRole> {
3979 self.cert.keys().with_policy(self.policy, self.time)
3980 }
3981
3982 /// Returns the primary User ID at the reference time, if any.
3983 ///
3984 /// A certificate may not have a primary User ID if it doesn't
3985 /// have any valid User IDs. If a certificate has at least one
3986 /// valid User ID at time `t`, then it has a primary User ID at
3987 /// time `t`.
3988 ///
3989 /// The primary User ID is determined as follows:
3990 ///
3991 /// - Discard User IDs that are not valid or not alive at time `t`.
3992 ///
3993 /// - Order the remaining User IDs by whether a User ID does not
3994 /// have a valid self-revocation (i.e., non-revoked first,
3995 /// ignoring third-party revocations).
3996 ///
3997 /// - Break ties by ordering by whether the User ID is [marked
3998 /// as being the primary User ID].
3999 ///
4000 /// - Break ties by ordering by the binding signature's creation
4001 /// time, most recent first.
4002 ///
4003 /// If there are multiple User IDs that are ordered first, then
4004 /// one is chosen in a deterministic, but undefined manner
4005 /// (currently, we order the value of the User IDs
4006 /// lexographically, but you shouldn't rely on this).
4007 ///
4008 /// [marked as being the primary User ID]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.27
4009 ///
4010 /// # Examples
4011 ///
4012 /// ```
4013 /// use std::time;
4014 /// use sequoia_openpgp as openpgp;
4015 /// use openpgp::cert::prelude::*;
4016 /// use openpgp::packet::prelude::*;
4017 /// use openpgp::policy::StandardPolicy;
4018 ///
4019 /// # fn main() -> openpgp::Result<()> {
4020 /// let p = &StandardPolicy::new();
4021 ///
4022 /// let t1 = time::SystemTime::now();
4023 /// let t2 = t1 + time::Duration::from_secs(1);
4024 ///
4025 /// let (cert, _) = CertBuilder::new()
4026 /// .set_creation_time(t1)
4027 /// .add_userid("Alice")
4028 /// .generate()?;
4029 /// let mut signer = cert
4030 /// .primary_key().key().clone().parts_into_secret()?.into_keypair()?;
4031 ///
4032 /// // There is only one User ID. It must be the primary User ID.
4033 /// let vc = cert.with_policy(p, t1)?;
4034 /// let alice = vc.primary_userid().unwrap();
4035 /// assert_eq!(alice.userid().value(), b"Alice");
4036 /// // By default, the primary User ID flag is set.
4037 /// assert!(alice.binding_signature().primary_userid().is_some());
4038 ///
4039 /// let template: signature::SignatureBuilder
4040 /// = alice.binding_signature().clone().into();
4041 ///
4042 /// // Add another user id whose creation time is after the
4043 /// // existing User ID, and doesn't have the User ID set.
4044 /// let sig = template.clone()
4045 /// .set_signature_creation_time(t2)?
4046 /// .set_primary_userid(false)?;
4047 /// let bob: UserID = "Bob".into();
4048 /// let sig = bob.bind(&mut signer, &cert, sig)?;
4049 /// let cert = cert.insert_packets(vec![Packet::from(bob), sig.into()])?.0;
4050 /// # assert_eq!(cert.userids().count(), 2);
4051 ///
4052 /// // Alice should still be the primary User ID, because it has the
4053 /// // primary User ID flag set.
4054 /// let alice = cert.with_policy(p, t2)?.primary_userid().unwrap();
4055 /// assert_eq!(alice.userid().value(), b"Alice");
4056 ///
4057 ///
4058 /// // Add another User ID, whose binding signature's creation
4059 /// // time is after Alice's and also has the primary User ID flag set.
4060 /// let sig = template.clone()
4061 /// .set_signature_creation_time(t2)?;
4062 /// let carol: UserID = "Carol".into();
4063 /// let sig = carol.bind(&mut signer, &cert, sig)?;
4064 /// let cert = cert.insert_packets(vec![Packet::from(carol), sig.into()])?.0;
4065 /// # assert_eq!(cert.userids().count(), 3);
4066 ///
4067 /// // It should now be the primary User ID, because it is the
4068 /// // newest User ID with the primary User ID bit is set.
4069 /// let carol = cert.with_policy(p, t2)?.primary_userid().unwrap();
4070 /// assert_eq!(carol.userid().value(), b"Carol");
4071 /// # Ok(()) }
4072 pub fn primary_userid(&self) -> Result<ValidUserIDAmalgamation<'a>>
4073 {
4074 self.cert.primary_userid_relaxed(self.policy(), self.time(), true)
4075 }
4076
4077 /// Returns an iterator over the certificate's valid User IDs.
4078 ///
4079 /// # Examples
4080 ///
4081 /// ```
4082 /// # use std::time;
4083 /// use sequoia_openpgp as openpgp;
4084 /// # use openpgp::cert::prelude::*;
4085 /// use openpgp::packet::prelude::*;
4086 /// use openpgp::policy::StandardPolicy;
4087 ///
4088 /// # fn main() -> openpgp::Result<()> {
4089 /// let p = &StandardPolicy::new();
4090 ///
4091 /// # let t0 = time::SystemTime::now() - time::Duration::from_secs(10);
4092 /// # let t1 = t0 + time::Duration::from_secs(1);
4093 /// # let t2 = t1 + time::Duration::from_secs(1);
4094 /// # let (cert, _) =
4095 /// # CertBuilder::general_purpose(Some("alice@example.org"))
4096 /// # .set_creation_time(t0)
4097 /// # .generate()?;
4098 /// // `cert` was created at t0. Add a second User ID at t1.
4099 /// let userid = UserID::from("alice@example.com");
4100 /// // Use the primary User ID's current binding signature as the
4101 /// // basis for the new User ID's binding signature.
4102 /// let template : signature::SignatureBuilder
4103 /// = cert.with_policy(p, None)?
4104 /// .primary_userid()?
4105 /// .binding_signature()
4106 /// .clone()
4107 /// .into();
4108 /// let sig = template.set_signature_creation_time(t1)?;
4109 /// let mut signer = cert
4110 /// .primary_key().key().clone().parts_into_secret()?.into_keypair()?;
4111 /// let binding = userid.bind(&mut signer, &cert, sig)?;
4112 /// // Merge it.
4113 /// let cert = cert.insert_packets(
4114 /// vec![Packet::from(userid), binding.into()])?.0;
4115 ///
4116 /// // At t0, the new User ID is not yet valid (it doesn't have a
4117 /// // binding signature that is live at t0). Thus, it is not
4118 /// // returned.
4119 /// let vc = cert.with_policy(p, t0)?;
4120 /// assert_eq!(vc.userids().count(), 1);
4121 /// // But, at t1, we see both User IDs.
4122 /// let vc = cert.with_policy(p, t1)?;
4123 /// assert_eq!(vc.userids().count(), 2);
4124 /// # Ok(())
4125 /// # }
4126 /// ```
4127 pub fn userids(&self) -> ValidUserIDAmalgamationIter<'a> {
4128 self.cert.userids().with_policy(self.policy, self.time)
4129 }
4130
4131 /// Returns the primary User Attribute, if any.
4132 ///
4133 /// If a certificate has any valid User Attributes, then it has a
4134 /// primary User Attribute. In other words, it will not have a
4135 /// primary User Attribute at time `t` if there are no valid User
4136 /// Attributes at time `t`.
4137 ///
4138 /// The primary User Attribute is determined in the same way as
4139 /// the primary User ID. See the documentation of
4140 /// [`ValidCert::primary_userid`] for details.
4141 ///
4142 /// [`ValidCert::primary_userid`]: ValidCert::primary_userid()
4143 ///
4144 /// # Examples
4145 ///
4146 /// ```
4147 /// use sequoia_openpgp as openpgp;
4148 /// # use openpgp::cert::prelude::*;
4149 /// use openpgp::policy::StandardPolicy;
4150 ///
4151 /// # fn main() -> openpgp::Result<()> {
4152 /// let p = &StandardPolicy::new();
4153 ///
4154 /// # let (cert, _) =
4155 /// # CertBuilder::general_purpose(Some("alice@example.org"))
4156 /// # .generate()?;
4157 /// let vc = cert.with_policy(p, None)?;
4158 /// let ua = vc.primary_user_attribute();
4159 /// # // We don't have a user attributes. So, this should return an
4160 /// # // error.
4161 /// # assert!(ua.is_err());
4162 /// # Ok(())
4163 /// # }
4164 /// ```
4165 pub fn primary_user_attribute(&self)
4166 -> Result<ValidComponentAmalgamation<'a, UserAttribute>>
4167 {
4168 ValidComponentAmalgamation::primary(self.cert,
4169 self.cert.user_attributes.iter(),
4170 self.policy(), self.time(), true)
4171 }
4172
4173 /// Returns an iterator over the certificate's valid
4174 /// `UserAttribute`s.
4175 ///
4176 /// # Examples
4177 ///
4178 /// ```
4179 /// use sequoia_openpgp as openpgp;
4180 /// # use openpgp::cert::prelude::*;
4181 /// # use openpgp::packet::prelude::*;
4182 /// # use openpgp::packet::user_attribute::Subpacket;
4183 /// use openpgp::policy::StandardPolicy;
4184 ///
4185 /// # fn main() -> openpgp::Result<()> {
4186 /// let p = &StandardPolicy::new();
4187 ///
4188 /// # let (cert, _) =
4189 /// # CertBuilder::general_purpose(Some("alice@example.org"))
4190 /// # .generate()?;
4191 /// #
4192 /// # // Create some user attribute. Doctests do not pass cfg(test),
4193 /// # // so UserAttribute::arbitrary is not available
4194 /// # let sp = Subpacket::Unknown(7, vec![7; 7].into_boxed_slice());
4195 /// # let ua = UserAttribute::new(&[sp]);
4196 /// #
4197 /// // Add a User Attribute without a self-signature to the certificate.
4198 /// let cert = cert.insert_packets(ua)?.0;
4199 /// assert_eq!(cert.user_attributes().count(), 1);
4200 ///
4201 /// // Without a self-signature, it is definitely not valid.
4202 /// let vc = cert.with_policy(p, None)?;
4203 /// assert_eq!(vc.user_attributes().count(), 0);
4204 /// # Ok(())
4205 /// # }
4206 /// ```
4207 pub fn user_attributes(&self) -> ValidUserAttributeAmalgamationIter<'a> {
4208 self.cert.user_attributes().with_policy(self.policy, self.time)
4209 }
4210
4211 /// Returns a list of any designated revokers for this certificate.
4212 ///
4213 /// This function returns the designated revokers listed on the
4214 /// primary key's binding signatures and the certificate's direct
4215 /// key signatures.
4216 ///
4217 /// Note: the returned list is deduplicated.
4218 ///
4219 /// In order to preserve our API during the 1.x series, this
4220 /// function takes an optional policy argument. It should be
4221 /// `None`, but if it is `Some(_)`, it will be used instead of the
4222 /// `ValidCert`'s policy. This makes the function signature
4223 /// compatible with [`Cert::revocation_keys`].
4224 ///
4225 /// # Examples
4226 ///
4227 /// ```
4228 /// use sequoia_openpgp as openpgp;
4229 /// # use openpgp::Result;
4230 /// use openpgp::cert::prelude::*;
4231 /// use openpgp::policy::StandardPolicy;
4232 /// use openpgp::types::RevocationKey;
4233 ///
4234 /// # fn main() -> Result<()> {
4235 /// let p = &StandardPolicy::new();
4236 ///
4237 /// let (alice, _) =
4238 /// CertBuilder::general_purpose(Some("alice@example.org"))
4239 /// .generate()?;
4240 /// // Make Alice a designated revoker for Bob.
4241 /// let (bob, _) =
4242 /// CertBuilder::general_purpose(Some("bob@example.org"))
4243 /// .set_revocation_keys(vec![(&alice).into()])
4244 /// .generate()?;
4245 ///
4246 /// // Make sure Alice is listed as a designated revoker for Bob.
4247 /// assert_eq!(bob.with_policy(p, None)?.revocation_keys()
4248 /// .collect::<Vec<&RevocationKey>>(),
4249 /// vec![&(&alice).into()]);
4250 /// # Ok(()) }
4251 /// ```
4252 pub fn revocation_keys(&self)
4253 -> impl Iterator<Item = &'a RevocationKey> + 'a
4254 {
4255 self.cert.revocation_keys(self.policy())
4256 }
4257
4258 /// Returns the certificate's fingerprint as a `KeyHandle`.
4259 ///
4260 /// # Examples
4261 ///
4262 /// ```
4263 /// # use sequoia_openpgp as openpgp;
4264 /// # use openpgp::cert::prelude::*;
4265 /// # use openpgp::KeyHandle;
4266 /// # use openpgp::policy::StandardPolicy;
4267 /// #
4268 /// # fn main() -> openpgp::Result<()> {
4269 /// let p = &StandardPolicy::new();
4270 ///
4271 /// # let (cert, _) =
4272 /// # CertBuilder::general_purpose(Some("alice@example.org"))
4273 /// # .generate()?;
4274 /// #
4275 /// println!("{}", cert.with_policy(p, None)?.key_handle());
4276 ///
4277 /// // This always returns a fingerprint.
4278 /// match cert.with_policy(p, None)?.key_handle() {
4279 /// KeyHandle::Fingerprint(_) => (),
4280 /// KeyHandle::KeyID(_) => unreachable!(),
4281 /// }
4282 /// #
4283 /// # Ok(())
4284 /// # }
4285 /// ```
4286 pub fn key_handle(&self) -> KeyHandle {
4287 self.cert().key_handle()
4288 }
4289
4290 /// Returns the certificate's fingerprint.
4291 ///
4292 /// # Examples
4293 ///
4294 /// ```
4295 /// # use sequoia_openpgp as openpgp;
4296 /// # use openpgp::cert::prelude::*;
4297 /// # use openpgp::policy::StandardPolicy;
4298 /// #
4299 /// # fn main() -> openpgp::Result<()> {
4300 /// let p = &StandardPolicy::new();
4301 ///
4302 /// # let (cert, _) =
4303 /// # CertBuilder::general_purpose(Some("alice@example.org"))
4304 /// # .generate()?;
4305 /// #
4306 /// println!("{}", cert.with_policy(p, None)?.fingerprint());
4307 /// #
4308 /// # Ok(())
4309 /// # }
4310 /// ```
4311 pub fn fingerprint(&self) -> Fingerprint {
4312 self.cert().fingerprint()
4313 }
4314
4315 /// Returns the certificate's Key ID.
4316 ///
4317 /// As a general rule of thumb, you should prefer the fingerprint
4318 /// as it is possible to create keys with a colliding Key ID using
4319 /// a [birthday attack].
4320 ///
4321 /// [birthday attack]: https://nullprogram.com/blog/2019/07/22/
4322 ///
4323 /// # Examples
4324 ///
4325 /// ```
4326 /// # use sequoia_openpgp as openpgp;
4327 /// # use openpgp::cert::prelude::*;
4328 /// # use openpgp::policy::StandardPolicy;
4329 /// #
4330 /// # fn main() -> openpgp::Result<()> {
4331 /// let p = &StandardPolicy::new();
4332 ///
4333 /// # let (cert, _) =
4334 /// # CertBuilder::general_purpose(Some("alice@example.org"))
4335 /// # .generate()?;
4336 /// #
4337 /// println!("{}", cert.with_policy(p, None)?.keyid());
4338 /// #
4339 /// # Ok(())
4340 /// # }
4341 /// ```
4342 pub fn keyid(&self) -> KeyID {
4343 self.cert().keyid()
4344 }
4345}
4346
4347macro_rules! impl_pref {
4348 ($subpacket:ident, $rt:ty) => {
4349 #[allow(deprecated)]
4350 fn $subpacket(&self) -> Option<$rt>
4351 {
4352 // When addressed by the fingerprint or keyid, we first
4353 // look on the primary User ID and then fall back to the
4354 // direct key signature. We need to be careful to handle
4355 // the case where there are no User IDs.
4356 #[allow(deprecated)]
4357 if let Ok(u) = self.primary_userid() {
4358 u.$subpacket()
4359 } else if let Ok(sig) = self.direct_key_signature() {
4360 sig.$subpacket()
4361 } else {
4362 None
4363 }
4364 }
4365 }
4366}
4367
4368impl<'a> seal::Sealed for ValidCert<'a> {}
4369impl<'a> Preferences<'a> for ValidCert<'a>
4370{
4371 impl_pref!(preferred_symmetric_algorithms, &'a [SymmetricAlgorithm]);
4372 impl_pref!(preferred_hash_algorithms, &'a [HashAlgorithm]);
4373 impl_pref!(preferred_compression_algorithms, &'a [CompressionAlgorithm]);
4374 impl_pref!(preferred_aead_ciphersuites, &'a [(SymmetricAlgorithm, AEADAlgorithm)]);
4375 impl_pref!(key_server_preferences, KeyServerPreferences);
4376 impl_pref!(preferred_key_server, &'a [u8]);
4377 impl_pref!(policy_uri, &'a [u8]);
4378 impl_pref!(features, Features);
4379}
4380
4381#[cfg(test)]
4382mod test {
4383 use std::convert::TryInto;
4384
4385 use crate::crypto::PublicKeyAlgorithm;
4386 use crate::serialize::Serialize;
4387 use crate::policy::StandardPolicy as P;
4388 use crate::types::Curve;
4389 use crate::packet::signature;
4390 use crate::policy::HashAlgoSecurity;
4391 use super::*;
4392
4393 use crate::{
4394 KeyID,
4395 types::KeyFlags,
4396 };
4397
4398 fn parse_cert(data: &[u8], as_message: bool) -> Result<Cert> {
4399 if as_message {
4400 let pile = PacketPile::from_bytes(data).unwrap();
4401 Cert::try_from(pile)
4402 } else {
4403 Cert::from_bytes(data)
4404 }
4405 }
4406
4407 #[test]
4408 fn broken() {
4409 use crate::types::Timestamp;
4410 for i in 0..2 {
4411 let cert = parse_cert(crate::tests::key("testy-broken-no-pk.pgp"),
4412 i == 0);
4413 assert_match!(Error::MalformedCert(_)
4414 = cert.err().unwrap().downcast::<Error>().unwrap());
4415
4416 // According to 4880, a Cert must have a UserID. But, we
4417 // don't require it.
4418 let cert = parse_cert(crate::tests::key("testy-broken-no-uid.pgp"),
4419 i == 0);
4420 assert!(cert.is_ok());
4421
4422 // We have:
4423 //
4424 // [ pk, user id, sig, subkey ]
4425 let cert = parse_cert(crate::tests::key("testy-broken-no-sig-on-subkey.pgp"),
4426 i == 0).unwrap();
4427 assert_eq!(cert.primary.key().creation_time(),
4428 Timestamp::from(1511355130).into());
4429 assert_eq!(cert.userids.len(), 1);
4430 assert_eq!(cert.userids[0].userid().value(),
4431 &b"Testy McTestface <testy@example.org>"[..]);
4432 assert_eq!(cert.userids[0].self_signatures().count(), 1);
4433 assert_eq!(cert.userids[0].self_signatures().next().unwrap()
4434 .digest_prefix(),
4435 &[ 0xc6, 0x8f ]);
4436 assert_eq!(cert.user_attributes.len(), 0);
4437 assert_eq!(cert.subkeys.len(), 1);
4438 }
4439 }
4440
4441 #[test]
4442 fn basics() {
4443 use crate::types::Timestamp;
4444 for i in 0..2 {
4445 let cert = parse_cert(crate::tests::key("testy.pgp"),
4446 i == 0).unwrap();
4447 assert_eq!(cert.primary.key().creation_time(),
4448 Timestamp::from(1511355130).into());
4449 assert_eq!(format!("{:X}", cert.fingerprint()),
4450 "3E8877C877274692975189F5D03F6F865226FE8B");
4451
4452 assert_eq!(cert.userids.len(), 1, "number of userids");
4453 assert_eq!(cert.userids[0].userid().value(),
4454 &b"Testy McTestface <testy@example.org>"[..]);
4455 assert_eq!(cert.userids[0].self_signatures().count(), 1);
4456 assert_eq!(cert.userids[0].self_signatures().next().unwrap()
4457 .digest_prefix(),
4458 &[ 0xc6, 0x8f ]);
4459
4460 assert_eq!(cert.user_attributes.len(), 0);
4461
4462 assert_eq!(cert.subkeys.len(), 1, "number of subkeys");
4463 assert_eq!(cert.subkeys[0].key().creation_time(),
4464 Timestamp::from(1511355130).into());
4465 assert_eq!(cert.subkeys[0].self_signatures().next().unwrap()
4466 .digest_prefix(),
4467 &[ 0xb7, 0xb9 ]);
4468
4469 let cert = parse_cert(crate::tests::key("testy-no-subkey.pgp"),
4470 i == 0).unwrap();
4471 assert_eq!(cert.primary.key().creation_time(),
4472 Timestamp::from(1511355130).into());
4473 assert_eq!(format!("{:X}", cert.fingerprint()),
4474 "3E8877C877274692975189F5D03F6F865226FE8B");
4475
4476 assert_eq!(cert.user_attributes.len(), 0);
4477
4478 assert_eq!(cert.userids.len(), 1, "number of userids");
4479 assert_eq!(cert.userids[0].userid().value(),
4480 &b"Testy McTestface <testy@example.org>"[..]);
4481 assert_eq!(cert.userids[0].self_signatures().count(), 1);
4482 assert_eq!(cert.userids[0].self_signatures().next().unwrap()
4483 .digest_prefix(),
4484 &[ 0xc6, 0x8f ]);
4485
4486 assert_eq!(cert.subkeys.len(), 0, "number of subkeys");
4487
4488 let cert = parse_cert(crate::tests::key("testy.asc"), i == 0).unwrap();
4489 assert_eq!(format!("{:X}", cert.fingerprint()),
4490 "3E8877C877274692975189F5D03F6F865226FE8B");
4491 }
4492 }
4493
4494 #[test]
4495 fn only_a_public_key() {
4496 // Make sure the Cert parser can parse a key that just consists
4497 // of a public key---no signatures, no user ids, nothing.
4498 let cert = Cert::from_bytes(crate::tests::key("testy-only-a-pk.pgp")).unwrap();
4499 assert_eq!(cert.userids.len(), 0);
4500 assert_eq!(cert.user_attributes.len(), 0);
4501 assert_eq!(cert.subkeys.len(), 0);
4502 }
4503
4504 #[test]
4505 fn merge() {
4506 use crate::tests::key;
4507 let cert_base = Cert::from_bytes(key("bannon-base.pgp")).unwrap();
4508
4509 // When we merge it with itself, we should get the exact same
4510 // thing.
4511 let merged = cert_base.clone().merge_public_and_secret(cert_base.clone()).unwrap();
4512 assert_eq!(cert_base, merged);
4513
4514 let cert_add_uid_1
4515 = Cert::from_bytes(key("bannon-add-uid-1-whitehouse.gov.pgp"))
4516 .unwrap();
4517 let cert_add_uid_2
4518 = Cert::from_bytes(key("bannon-add-uid-2-fox.com.pgp"))
4519 .unwrap();
4520 // Duplicate user id, but with a different self-sig.
4521 let cert_add_uid_3
4522 = Cert::from_bytes(key("bannon-add-uid-3-whitehouse.gov-dup.pgp"))
4523 .unwrap();
4524
4525 let cert_all_uids
4526 = Cert::from_bytes(key("bannon-all-uids.pgp"))
4527 .unwrap();
4528 // We have four User ID packets, but one has the same User ID,
4529 // just with a different self-signature.
4530 assert_eq!(cert_all_uids.userids.len(), 3);
4531
4532 // Merge in order.
4533 let merged = cert_base.clone().merge_public_and_secret(cert_add_uid_1.clone()).unwrap()
4534 .merge_public_and_secret(cert_add_uid_2.clone()).unwrap()
4535 .merge_public_and_secret(cert_add_uid_3.clone()).unwrap();
4536 assert_eq!(cert_all_uids, merged);
4537
4538 // Merge in reverse order.
4539 let merged = cert_base.clone()
4540 .merge_public_and_secret(cert_add_uid_3.clone()).unwrap()
4541 .merge_public_and_secret(cert_add_uid_2.clone()).unwrap()
4542 .merge_public_and_secret(cert_add_uid_1.clone()).unwrap();
4543 assert_eq!(cert_all_uids, merged);
4544
4545 let cert_add_subkey_1
4546 = Cert::from_bytes(key("bannon-add-subkey-1.pgp")).unwrap();
4547 let cert_add_subkey_2
4548 = Cert::from_bytes(key("bannon-add-subkey-2.pgp")).unwrap();
4549 let cert_add_subkey_3
4550 = Cert::from_bytes(key("bannon-add-subkey-3.pgp")).unwrap();
4551
4552 let cert_all_subkeys
4553 = Cert::from_bytes(key("bannon-all-subkeys.pgp")).unwrap();
4554
4555 // Merge the first user, then the second, then the third.
4556 let merged = cert_base.clone().merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4557 .merge_public_and_secret(cert_add_subkey_2.clone()).unwrap()
4558 .merge_public_and_secret(cert_add_subkey_3.clone()).unwrap();
4559 assert_eq!(cert_all_subkeys, merged);
4560
4561 // Merge the third user, then the second, then the first.
4562 let merged = cert_base.clone().merge_public_and_secret(cert_add_subkey_3.clone()).unwrap()
4563 .merge_public_and_secret(cert_add_subkey_2.clone()).unwrap()
4564 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap();
4565 assert_eq!(cert_all_subkeys, merged);
4566
4567 // Merge a lot.
4568 let merged = cert_base.clone()
4569 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4570 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4571 .merge_public_and_secret(cert_add_subkey_3.clone()).unwrap()
4572 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4573 .merge_public_and_secret(cert_add_subkey_2.clone()).unwrap()
4574 .merge_public_and_secret(cert_add_subkey_3.clone()).unwrap()
4575 .merge_public_and_secret(cert_add_subkey_3.clone()).unwrap()
4576 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4577 .merge_public_and_secret(cert_add_subkey_2.clone()).unwrap();
4578 assert_eq!(cert_all_subkeys, merged);
4579
4580 let cert_all
4581 = Cert::from_bytes(key("bannon-all-uids-subkeys.pgp"))
4582 .unwrap();
4583
4584 // Merge all the subkeys with all the uids.
4585 let merged = cert_all_subkeys.clone()
4586 .merge_public_and_secret(cert_all_uids.clone()).unwrap();
4587 assert_eq!(cert_all, merged);
4588
4589 // Merge all uids with all the subkeys.
4590 let merged = cert_all_uids.clone()
4591 .merge_public_and_secret(cert_all_subkeys.clone()).unwrap();
4592 assert_eq!(cert_all, merged);
4593
4594 // All the subkeys and the uids in a mixed up order.
4595 let merged = cert_base.clone()
4596 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4597 .merge_public_and_secret(cert_add_uid_2.clone()).unwrap()
4598 .merge_public_and_secret(cert_add_uid_1.clone()).unwrap()
4599 .merge_public_and_secret(cert_add_subkey_3.clone()).unwrap()
4600 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4601 .merge_public_and_secret(cert_add_uid_3.clone()).unwrap()
4602 .merge_public_and_secret(cert_add_subkey_2.clone()).unwrap()
4603 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4604 .merge_public_and_secret(cert_add_uid_2.clone()).unwrap();
4605 assert_eq!(cert_all, merged);
4606
4607 // Certifications.
4608 let cert_donald_signs_base
4609 = Cert::from_bytes(key("bannon-the-donald-signs-base.pgp"))
4610 .unwrap();
4611 let cert_donald_signs_all
4612 = Cert::from_bytes(key("bannon-the-donald-signs-all-uids.pgp"))
4613 .unwrap();
4614 let cert_ivanka_signs_base
4615 = Cert::from_bytes(key("bannon-ivanka-signs-base.pgp"))
4616 .unwrap();
4617 let cert_ivanka_signs_all
4618 = Cert::from_bytes(key("bannon-ivanka-signs-all-uids.pgp"))
4619 .unwrap();
4620
4621 assert!(cert_donald_signs_base.userids.len() == 1);
4622 assert!(cert_donald_signs_base.userids[0].self_signatures().count() == 1);
4623 assert!(cert_base.userids[0].certifications.is_empty());
4624 assert!(cert_donald_signs_base.userids[0].certifications.len() == 1);
4625
4626 let merged = cert_donald_signs_base.clone()
4627 .merge_public_and_secret(cert_ivanka_signs_base.clone()).unwrap();
4628 assert!(merged.userids.len() == 1);
4629 assert!(merged.userids[0].self_signatures().count() == 1);
4630 assert!(merged.userids[0].certifications.len() == 2);
4631
4632 let merged = cert_donald_signs_base.clone()
4633 .merge_public_and_secret(cert_donald_signs_all.clone()).unwrap();
4634 assert!(merged.userids.len() == 3);
4635 assert!(merged.userids[0].self_signatures().count() == 1);
4636 // There should be two certifications from the Donald on the
4637 // first user id.
4638 assert!(merged.userids[0].certifications.len() == 2);
4639 assert!(merged.userids[1].certifications.len() == 1);
4640 assert!(merged.userids[2].certifications.len() == 1);
4641
4642 let merged = cert_donald_signs_base.clone()
4643 .merge_public_and_secret(cert_donald_signs_all.clone()).unwrap()
4644 .merge_public_and_secret(cert_ivanka_signs_base.clone()).unwrap()
4645 .merge_public_and_secret(cert_ivanka_signs_all.clone()).unwrap();
4646 assert!(merged.userids.len() == 3);
4647 assert!(merged.userids[0].self_signatures().count() == 1);
4648 // There should be two certifications from each of the Donald
4649 // and Ivanka on the first user id, and one each on the rest.
4650 assert!(merged.userids[0].certifications.len() == 4);
4651 assert!(merged.userids[1].certifications.len() == 2);
4652 assert!(merged.userids[2].certifications.len() == 2);
4653
4654 // Same as above, but redundant.
4655 let merged = cert_donald_signs_base.clone()
4656 .merge_public_and_secret(cert_ivanka_signs_base.clone()).unwrap()
4657 .merge_public_and_secret(cert_donald_signs_all.clone()).unwrap()
4658 .merge_public_and_secret(cert_donald_signs_all.clone()).unwrap()
4659 .merge_public_and_secret(cert_ivanka_signs_all.clone()).unwrap()
4660 .merge_public_and_secret(cert_ivanka_signs_base.clone()).unwrap()
4661 .merge_public_and_secret(cert_donald_signs_all.clone()).unwrap()
4662 .merge_public_and_secret(cert_donald_signs_all.clone()).unwrap()
4663 .merge_public_and_secret(cert_ivanka_signs_all.clone()).unwrap();
4664 assert!(merged.userids.len() == 3);
4665 assert!(merged.userids[0].self_signatures().count() == 1);
4666 // There should be two certifications from each of the Donald
4667 // and Ivanka on the first user id, and one each on the rest.
4668 assert!(merged.userids[0].certifications.len() == 4);
4669 assert!(merged.userids[1].certifications.len() == 2);
4670 assert!(merged.userids[2].certifications.len() == 2);
4671 }
4672
4673 #[test]
4674 fn out_of_order_self_sigs_test() {
4675 // neal-out-of-order.pgp contains all the self-signatures,
4676 // but some are out of order. The canonicalization step
4677 // should reorder them.
4678 //
4679 // original order/new order:
4680 //
4681 // 1/ 1. pk
4682 // 2/ 2. user id #1: neal@walfield.org (good)
4683 // 3/ 3. sig over user ID #1
4684 //
4685 // 4/ 4. user id #2: neal@gnupg.org (good)
4686 // 5/ 7. sig over user ID #3
4687 // 6/ 5. sig over user ID #2
4688 //
4689 // 7/ 6. user id #3: neal@g10code.com (bad)
4690 //
4691 // 8/ 8. user ID #4: neal@pep.foundation (bad)
4692 // 9/11. sig over user ID #5
4693 //
4694 // 10/10. user id #5: neal@pep-project.org (bad)
4695 // 11/ 9. sig over user ID #4
4696 //
4697 // 12/12. user ID #6: neal@sequoia-pgp.org (good)
4698 // 13/13. sig over user ID #6
4699 //
4700 // ----------------------------------------------
4701 //
4702 // 14/14. signing subkey #1: 7223B56678E02528 (good)
4703 // 15/15. sig over subkey #1
4704 // 16/16. sig over subkey #1
4705 //
4706 // 17/17. encryption subkey #2: C2B819056C652598 (good)
4707 // 18/18. sig over subkey #2
4708 // 19/21. sig over subkey #3
4709 // 20/22. sig over subkey #3
4710 //
4711 // 21/20. auth subkey #3: A3506AFB820ABD08 (bad)
4712 // 22/19. sig over subkey #2
4713
4714 let cert = Cert::from_bytes(crate::tests::key("neal-sigs-out-of-order.pgp"))
4715 .unwrap();
4716
4717 let mut userids = cert.userids()
4718 .map(|u| String::from_utf8_lossy(u.userid().value()).into_owned())
4719 .collect::<Vec<String>>();
4720 userids.sort();
4721
4722 assert_eq!(userids,
4723 &[ "Neal H. Walfield <neal@g10code.com>",
4724 "Neal H. Walfield <neal@gnupg.org>",
4725 "Neal H. Walfield <neal@pep-project.org>",
4726 "Neal H. Walfield <neal@pep.foundation>",
4727 "Neal H. Walfield <neal@sequoia-pgp.org>",
4728 "Neal H. Walfield <neal@walfield.org>",
4729 ]);
4730
4731 let mut subkeys = cert.subkeys()
4732 .map(|sk| Some(sk.key().keyid()))
4733 .collect::<Vec<Option<KeyID>>>();
4734 subkeys.sort();
4735 assert_eq!(subkeys,
4736 &[ "7223B56678E02528".parse().ok(),
4737 "A3506AFB820ABD08".parse().ok(),
4738 "C2B819056C652598".parse().ok(),
4739 ]);
4740
4741 // DKG's key has all the self-signatures moved to the last
4742 // subkey; all user ids/user attributes/subkeys have nothing.
4743 let cert =
4744 Cert::from_bytes(crate::tests::key("dkg-sigs-out-of-order.pgp")).unwrap();
4745
4746 let mut userids = cert.userids()
4747 .map(|u| String::from_utf8_lossy(u.userid().value()).into_owned())
4748 .collect::<Vec<String>>();
4749 userids.sort();
4750
4751 assert_eq!(userids,
4752 &[ "Daniel Kahn Gillmor <dkg-debian.org@fifthhorseman.net>",
4753 "Daniel Kahn Gillmor <dkg@aclu.org>",
4754 "Daniel Kahn Gillmor <dkg@astro.columbia.edu>",
4755 "Daniel Kahn Gillmor <dkg@debian.org>",
4756 "Daniel Kahn Gillmor <dkg@fifthhorseman.net>",
4757 "Daniel Kahn Gillmor <dkg@openflows.com>",
4758 ]);
4759
4760 assert_eq!(cert.user_attributes.len(), 1);
4761
4762 let mut subkeys = cert.subkeys()
4763 .map(|sk| Some(sk.key().keyid()))
4764 .collect::<Vec<Option<KeyID>>>();
4765 subkeys.sort();
4766 assert_eq!(subkeys,
4767 &[ "1075 8EBD BD7C FAB5".parse().ok(),
4768 "1258 68EA 4BFA 08E4".parse().ok(),
4769 "1498 ADC6 C192 3237".parse().ok(),
4770 "24EC FF5A FF68 370A".parse().ok(),
4771 "3714 7292 14D5 DA70".parse().ok(),
4772 "3B7A A7F0 14E6 9B5A".parse().ok(),
4773 "5B58 DCF9 C341 6611".parse().ok(),
4774 "A524 01B1 1BFD FA5C".parse().ok(),
4775 "A70A 96E1 439E A852".parse().ok(),
4776 "C61B D3EC 2148 4CFF".parse().ok(),
4777 "CAEF A883 2167 5333".parse().ok(),
4778 "DC10 4C4E 0CA7 57FB".parse().ok(),
4779 "E3A3 2229 449B 0350".parse().ok(),
4780 ]);
4781
4782 }
4783
4784 /// Tests how we deal with v3 keys, certs, and certifications.
4785 #[test]
4786 fn v3_packets() {
4787 // v3 primary keys are not supported.
4788
4789 let cert = Cert::from_bytes(crate::tests::key("john-v3.pgp"));
4790 assert_match!(Error::UnsupportedCert(..)
4791 = cert.err().unwrap().downcast::<Error>().unwrap());
4792
4793 let cert = Cert::from_bytes(crate::tests::key("john-v3-secret.pgp"));
4794 assert_match!(Error::UnsupportedCert(..)
4795 = cert.err().unwrap().downcast::<Error>().unwrap());
4796
4797 // Lutz's key is a v3 key.
4798 let cert = Cert::from_bytes(crate::tests::key("lutz.pgp"));
4799 assert_match!(Error::UnsupportedCert(..)
4800 = cert.err().unwrap().downcast::<Error>().unwrap());
4801
4802 // v3 certifications are not supported
4803
4804 // dkg's includes some v3 signatures.
4805 let cert = Cert::from_bytes(crate::tests::key("dkg.pgp"));
4806 assert!(cert.is_ok(), "dkg.pgp: {:?}", cert);
4807 }
4808
4809 #[test]
4810 fn keyring_with_v3_public_keys() {
4811 let dkg = crate::tests::key("dkg.pgp");
4812 let lutz = crate::tests::key("lutz.pgp");
4813
4814 let cert = Cert::from_bytes(dkg);
4815 assert!(cert.is_ok(), "dkg.pgp: {:?}", cert);
4816
4817 // Keyring with two good keys
4818 let mut combined = vec![];
4819 combined.extend_from_slice(dkg);
4820 combined.extend_from_slice(dkg);
4821 let certs = CertParser::from_bytes(&combined[..]).unwrap()
4822 .map(|certr| certr.is_ok())
4823 .collect::<Vec<bool>>();
4824 assert_eq!(certs, &[ true, true ]);
4825
4826 // Keyring with a good key, and a bad key.
4827 let mut combined = vec![];
4828 combined.extend_from_slice(dkg);
4829 combined.extend_from_slice(lutz);
4830 let certs = CertParser::from_bytes(&combined[..]).unwrap()
4831 .map(|certr| certr.is_ok())
4832 .collect::<Vec<bool>>();
4833 assert_eq!(certs, &[ true, false ]);
4834
4835 // Keyring with a bad key, and a good key.
4836 let mut combined = vec![];
4837 combined.extend_from_slice(lutz);
4838 combined.extend_from_slice(dkg);
4839 let certs = CertParser::from_bytes(&combined[..]).unwrap()
4840 .map(|certr| certr.is_ok())
4841 .collect::<Vec<bool>>();
4842 assert_eq!(certs, &[ false, true ]);
4843
4844 // Keyring with a good key, a bad key, and a good key.
4845 let mut combined = vec![];
4846 combined.extend_from_slice(dkg);
4847 combined.extend_from_slice(lutz);
4848 combined.extend_from_slice(dkg);
4849 let certs = CertParser::from_bytes(&combined[..]).unwrap()
4850 .map(|certr| certr.is_ok())
4851 .collect::<Vec<bool>>();
4852 assert_eq!(certs, &[ true, false, true ]);
4853
4854 // Keyring with a good key, a bad key, and a bad key.
4855 let mut combined = vec![];
4856 combined.extend_from_slice(dkg);
4857 combined.extend_from_slice(lutz);
4858 combined.extend_from_slice(lutz);
4859 let certs = CertParser::from_bytes(&combined[..]).unwrap()
4860 .map(|certr| certr.is_ok())
4861 .collect::<Vec<bool>>();
4862 assert_eq!(certs, &[ true, false, false ]);
4863
4864 // Keyring with a good key, a bad key, a bad key, and a good key.
4865 let mut combined = vec![];
4866 combined.extend_from_slice(dkg);
4867 combined.extend_from_slice(lutz);
4868 combined.extend_from_slice(lutz);
4869 combined.extend_from_slice(dkg);
4870 let certs = CertParser::from_bytes(&combined[..]).unwrap()
4871 .map(|certr| certr.is_ok())
4872 .collect::<Vec<bool>>();
4873 assert_eq!(certs, &[ true, false, false, true ]);
4874 }
4875
4876 #[test]
4877 fn merge_with_incomplete_update() {
4878 let p = &P::new();
4879
4880 let cert = Cert::from_bytes(crate::tests::key("about-to-expire.expired.pgp"))
4881 .unwrap();
4882 cert.primary_key().with_policy(p, None).unwrap().alive().unwrap_err();
4883
4884 let update =
4885 Cert::from_bytes(crate::tests::key("about-to-expire.update-no-uid.pgp"))
4886 .unwrap();
4887 let cert = cert.merge_public_and_secret(update).unwrap();
4888 cert.primary_key().with_policy(p, None).unwrap().alive().unwrap();
4889 }
4890
4891 #[test]
4892 fn packet_pile_roundtrip() {
4893 // Make sure Cert::try_from(Cert::to_packet_pile(cert))
4894 // does a clean round trip.
4895
4896 let cert = Cert::from_bytes(crate::tests::key("already-revoked.pgp")).unwrap();
4897 let cert2
4898 = Cert::try_from(cert.clone().into_packet_pile()).unwrap();
4899 assert_eq!(cert, cert2);
4900
4901 let cert = Cert::from_bytes(
4902 crate::tests::key("already-revoked-direct-revocation.pgp")).unwrap();
4903 let cert2
4904 = Cert::try_from(cert.clone().into_packet_pile()).unwrap();
4905 assert_eq!(cert, cert2);
4906
4907 let cert = Cert::from_bytes(
4908 crate::tests::key("already-revoked-userid-revocation.pgp")).unwrap();
4909 let cert2
4910 = Cert::try_from(cert.clone().into_packet_pile()).unwrap();
4911 assert_eq!(cert, cert2);
4912
4913 let cert = Cert::from_bytes(
4914 crate::tests::key("already-revoked-subkey-revocation.pgp")).unwrap();
4915 let cert2
4916 = Cert::try_from(cert.clone().into_packet_pile()).unwrap();
4917 assert_eq!(cert, cert2);
4918 }
4919
4920 #[test]
4921 fn insert_packets_add_sig() {
4922 use crate::armor;
4923 use crate::packet::Tag;
4924
4925 // Merge the revocation certificate into the Cert and make sure
4926 // it shows up.
4927 let cert = Cert::from_bytes(crate::tests::key("already-revoked.pgp")).unwrap();
4928
4929 let rev = crate::tests::key("already-revoked.rev");
4930 let rev = PacketPile::from_reader(armor::Reader::from_reader(rev, None))
4931 .unwrap();
4932
4933 let rev : Vec<Packet> = rev.into_children().collect();
4934 assert_eq!(rev.len(), 1);
4935 assert_eq!(rev[0].tag(), Tag::Signature);
4936
4937 let packets_pre_merge = cert.clone().into_packets().count();
4938 let cert = cert.insert_packets(rev).unwrap().0;
4939 let packets_post_merge = cert.clone().into_packets().count();
4940 assert_eq!(packets_post_merge, packets_pre_merge + 1);
4941 }
4942
4943 #[test]
4944 fn insert_packets_update_sig() -> Result<()> {
4945 use std::time::Duration;
4946
4947 use crate::packet::signature::subpacket::Subpacket;
4948 use crate::packet::signature::subpacket::SubpacketValue;
4949
4950 let (cert, _) = CertBuilder::general_purpose(Some("Test"))
4951 .generate()?;
4952 let packets = cert.clone().into_packets().count();
4953
4954 // Merge a signature with different unhashed subpacket areas.
4955 // Make sure only the last variant is merged.
4956 let sig = cert.primary_key().self_signatures().next()
4957 .expect("binding signature");
4958
4959 let a = Subpacket::new(
4960 SubpacketValue::SignatureExpirationTime(
4961 Duration::new(1, 0).try_into()?),
4962 false)?;
4963 let b = Subpacket::new(
4964 SubpacketValue::SignatureExpirationTime(
4965 Duration::new(2, 0).try_into()?),
4966 false)?;
4967
4968 let mut sig_a = sig.clone();
4969 sig_a.unhashed_area_mut().add(a)?;
4970 let mut sig_b = sig.clone();
4971 sig_b.unhashed_area_mut().add(b)?;
4972
4973 // Insert sig_a, make sure it (and it alone) appears.
4974 let cert2 = cert.clone().insert_packets(sig_a.clone())?.0;
4975 let mut sigs = cert2.primary_key().self_signatures();
4976 assert_eq!(sigs.next(), Some(&sig_a));
4977 assert!(sigs.next().is_none());
4978 assert_eq!(cert2.clone().into_packets().count(), packets);
4979
4980 // Insert sig_b, make sure it (and it alone) appears.
4981 let cert2 = cert.clone().insert_packets(sig_b.clone())?.0;
4982 let mut sigs = cert2.primary_key().self_signatures();
4983 assert_eq!(sigs.next(), Some(&sig_b));
4984 assert!(sigs.next().is_none());
4985 assert_eq!(cert2.clone().into_packets().count(), packets);
4986
4987 // Insert sig_a and sig_b. Make sure sig_b (and it alone)
4988 // appears.
4989 let cert2 = cert.clone().insert_packets(
4990 vec![ sig_a.clone(), sig_b.clone() ])?.0;
4991 let mut sigs = cert2.primary_key().self_signatures();
4992 assert_eq!(sigs.next(), Some(&sig_b));
4993 assert!(sigs.next().is_none());
4994 assert_eq!(cert2.clone().into_packets().count(), packets);
4995
4996 // Insert sig_b and sig_a. Make sure sig_a (and it alone)
4997 // appears.
4998 let cert2 = cert.clone().insert_packets(
4999 vec![ sig_b.clone(), sig_a.clone() ])?.0;
5000 let mut sigs = cert2.primary_key().self_signatures();
5001 assert_eq!(sigs.next(), Some(&sig_a));
5002 assert!(sigs.next().is_none());
5003 assert_eq!(cert2.clone().into_packets().count(), packets);
5004
5005 Ok(())
5006 }
5007
5008 #[test]
5009 fn insert_packets_add_userid() -> Result<()> {
5010 let (cert, _) = CertBuilder::general_purpose(Some("a"))
5011 .generate()?;
5012 let packets = cert.clone().into_packets().count();
5013
5014 let uid_a = UserID::from("a");
5015 let uid_b = UserID::from("b");
5016
5017 // Insert a, make sure it appears once.
5018 let cert2 = cert.clone().insert_packets(uid_a.clone())?.0;
5019 let mut uids = cert2.userids();
5020 assert_eq!(uids.next().unwrap().userid(), &uid_a);
5021 assert!(uids.next().is_none());
5022 assert_eq!(cert2.clone().into_packets().count(), packets);
5023
5024 // Insert b, make sure it also appears.
5025 let cert2 = cert.clone().insert_packets(uid_b.clone())?.0;
5026 let mut uids: Vec<UserID>
5027 = cert2.userids().map(|ua| ua.userid().clone()).collect();
5028 uids.sort();
5029 let mut uids = uids.iter();
5030 assert_eq!(uids.next().unwrap(), &uid_a);
5031 assert_eq!(uids.next().unwrap(), &uid_b);
5032 assert!(uids.next().is_none());
5033 assert_eq!(cert2.clone().into_packets().count(), packets + 1);
5034
5035 Ok(())
5036 }
5037
5038 #[test]
5039 fn insert_packets_update_key() -> Result<()> {
5040 use crate::crypto::Password;
5041
5042 let (cert, _) = CertBuilder::new().generate()?;
5043 let packets = cert.clone().into_packets().count();
5044 assert_eq!(cert.keys().count(), 1);
5045
5046 let key = cert.keys().secret().next().unwrap().key()
5047 .role_as_primary();
5048 assert!(key.has_secret());
5049 let key_a = key.clone().encrypt_secret(&Password::from("a"))?;
5050 let key_b = key.clone().encrypt_secret(&Password::from("b"))?;
5051
5052 // Insert variant a.
5053 let cert2 = cert.clone().insert_packets(key_a.clone())?.0;
5054 assert_eq!(cert2.primary_key().key().parts_as_secret().unwrap(),
5055 &key_a);
5056 assert_eq!(cert2.clone().into_packets().count(), packets);
5057
5058 // Insert variant b.
5059 let cert2 = cert.clone().insert_packets(key_b.clone())?.0;
5060 assert_eq!(cert2.primary_key().key().parts_as_secret().unwrap(),
5061 &key_b);
5062 assert_eq!(cert2.clone().into_packets().count(), packets);
5063
5064 // Insert variant a then b. We should keep b.
5065 let cert2 = cert.clone().insert_packets(
5066 vec![ key_a.clone(), key_b.clone() ])?.0;
5067 assert_eq!(cert2.primary_key().key().parts_as_secret().unwrap(),
5068 &key_b);
5069 assert_eq!(cert2.clone().into_packets().count(), packets);
5070
5071 // Insert variant b then a. We should keep a.
5072 let cert2 = cert.clone().insert_packets(
5073 vec![ key_b.clone(), key_a.clone() ])?.0;
5074 assert_eq!(cert2.primary_key().key().parts_as_secret().unwrap(),
5075 &key_a);
5076 assert_eq!(cert2.clone().into_packets().count(), packets);
5077
5078 Ok(())
5079 }
5080
5081 #[test]
5082 fn set_validity_period() {
5083 let p = &P::new();
5084
5085 let (cert, _) = CertBuilder::general_purpose(Some("Test"))
5086 .generate().unwrap();
5087 assert_eq!(cert.clone().into_packet_pile().children().count(),
5088 1 // primary key
5089 + 1 // direct key signature
5090 + 1 // userid
5091 + 1 // binding signature
5092 + 1 // subkey
5093 + 1 // binding signature
5094 + 1 // subkey
5095 + 1 // binding signature
5096 );
5097 let cert = check_set_validity_period(p, cert);
5098 assert_eq!(cert.clone().into_packet_pile().children().count(),
5099 1 // primary key
5100 + 1 // direct key signature
5101 + 2 // two new direct key signatures
5102 + 1 // userid
5103 + 1 // binding signature
5104 + 2 // two new binding signatures
5105 + 1 // subkey
5106 + 1 // binding signature
5107 + 1 // subkey
5108 + 1 // binding signature
5109 );
5110 }
5111
5112 #[test]
5113 fn set_validity_period_two_uids() -> Result<()> {
5114 use quickcheck::{Arbitrary, Gen};
5115 let mut gen = Gen::new(16);
5116 let p = &P::new();
5117
5118 let userid1 = UserID::arbitrary(&mut gen);
5119 // The two user ids need to be unique.
5120 let mut userid2 = UserID::arbitrary(&mut gen);
5121 while userid1 == userid2 {
5122 userid2 = UserID::arbitrary(&mut gen);
5123 }
5124
5125 let (cert, _) = CertBuilder::general_purpose(
5126 Some(userid1))
5127 .add_userid(userid2)
5128 .generate()?;
5129 let primary_uid = cert.with_policy(p, None)?.primary_userid()?.userid().clone();
5130 assert_eq!(cert.clone().into_packet_pile().children().count(),
5131 1 // primary key
5132 + 1 // direct key signature
5133 + 1 // userid
5134 + 1 // binding signature
5135 + 1 // userid
5136 + 1 // binding signature
5137 + 1 // subkey
5138 + 1 // binding signature
5139 + 1 // subkey
5140 + 1 // binding signature
5141 );
5142 let cert = check_set_validity_period(p, cert);
5143 assert_eq!(cert.clone().into_packet_pile().children().count(),
5144 1 // primary key
5145 + 1 // direct key signature
5146 + 2 // two new direct key signatures
5147 + 1 // userid
5148 + 1 // binding signature
5149 + 2 // two new binding signatures
5150 + 1 // userid
5151 + 1 // binding signature
5152 + 2 // two new binding signatures
5153 + 1 // subkey
5154 + 1 // binding signature
5155 + 1 // subkey
5156 + 1 // binding signature
5157 );
5158 assert_eq!(&primary_uid, cert.with_policy(p, None)?.primary_userid()?.userid());
5159 Ok(())
5160 }
5161
5162 #[test]
5163 fn set_validity_period_uidless() {
5164 use crate::types::Duration;
5165 let p = &P::new();
5166
5167 let (cert, _) = CertBuilder::new()
5168 .set_validity_period(None) // Just to assert this works.
5169 .set_validity_period(Some(Duration::weeks(52).unwrap().try_into().unwrap()))
5170 .generate().unwrap();
5171 assert_eq!(cert.clone().into_packet_pile().children().count(),
5172 1 // primary key
5173 + 1 // direct key signature
5174 );
5175 let cert = check_set_validity_period(p, cert);
5176 assert_eq!(cert.clone().into_packet_pile().children().count(),
5177 1 // primary key
5178 + 1 // direct key signature
5179 + 2 // two new direct key signatures
5180 );
5181 }
5182 fn check_set_validity_period(policy: &dyn Policy, cert: Cert) -> Cert {
5183 let now = cert.primary_key().key().creation_time();
5184 let a_sec = time::Duration::new(1, 0);
5185
5186 let expiry_orig = cert.primary_key().with_policy(policy, now).unwrap()
5187 .key_validity_period()
5188 .expect("Keys expire by default.");
5189
5190 let mut keypair = cert.primary_key().key().clone().parts_into_secret()
5191 .unwrap().into_keypair().unwrap();
5192
5193 // Clear the expiration.
5194 let as_of1 = now + time::Duration::new(10, 0);
5195 let cert = cert.set_validity_period_as_of(
5196 policy, &mut keypair, None, as_of1).unwrap();
5197 {
5198 // If t < as_of1, we should get the original expiry.
5199 assert_eq!(cert.primary_key().with_policy(policy, now).unwrap()
5200 .key_validity_period(),
5201 Some(expiry_orig));
5202 assert_eq!(cert.primary_key().with_policy(policy, as_of1 - a_sec).unwrap()
5203 .key_validity_period(),
5204 Some(expiry_orig));
5205 // If t >= as_of1, we should get the new expiry.
5206 assert_eq!(cert.primary_key().with_policy(policy, as_of1).unwrap()
5207 .key_validity_period(),
5208 None);
5209 }
5210
5211 // Shorten the expiry. (The default expiration should be at
5212 // least a few weeks, so removing an hour should still keep us
5213 // over 0.)
5214 let expiry_new = expiry_orig - time::Duration::new(60 * 60, 0);
5215 assert!(expiry_new > time::Duration::new(0, 0));
5216
5217 let as_of2 = as_of1 + time::Duration::new(10, 0);
5218 let cert = cert.set_validity_period_as_of(
5219 policy, &mut keypair, Some(expiry_new), as_of2).unwrap();
5220 {
5221 // If t < as_of1, we should get the original expiry.
5222 assert_eq!(cert.primary_key().with_policy(policy, now).unwrap()
5223 .key_validity_period(),
5224 Some(expiry_orig));
5225 assert_eq!(cert.primary_key().with_policy(policy, as_of1 - a_sec).unwrap()
5226 .key_validity_period(),
5227 Some(expiry_orig));
5228 // If as_of1 <= t < as_of2, we should get the second
5229 // expiry (None).
5230 assert_eq!(cert.primary_key().with_policy(policy, as_of1).unwrap()
5231 .key_validity_period(),
5232 None);
5233 assert_eq!(cert.primary_key().with_policy(policy, as_of2 - a_sec).unwrap()
5234 .key_validity_period(),
5235 None);
5236 // If t <= as_of2, we should get the new expiry.
5237 assert_eq!(cert.primary_key().with_policy(policy, as_of2).unwrap()
5238 .key_validity_period(),
5239 Some(expiry_new));
5240 }
5241 cert
5242 }
5243
5244 #[test]
5245 fn direct_key_sig() {
5246 use crate::types::SignatureType;
5247 // XXX: testing sequoia against itself isn't optimal, but I couldn't
5248 // find a tool to generate direct key signatures :-(
5249
5250 let p = &P::new();
5251
5252 let (cert1, _) = CertBuilder::new().generate().unwrap();
5253 let mut buf = Vec::default();
5254
5255 cert1.serialize(&mut buf).unwrap();
5256 let cert2 = Cert::from_bytes(&buf).unwrap();
5257
5258 assert_eq!(
5259 cert2.primary_key().with_policy(p, None).unwrap()
5260 .direct_key_signature().unwrap().typ(),
5261 SignatureType::DirectKey);
5262 assert_eq!(cert2.userids().count(), 0);
5263 }
5264
5265 #[test]
5266 fn revoked() {
5267 fn check(cert: &Cert, direct_revoked: bool,
5268 userid_revoked: bool, subkey_revoked: bool) {
5269 let p = &P::new();
5270
5271 // If we have a user id---even if it is revoked---we have
5272 // a primary key signature.
5273 let typ = cert.primary_key().with_policy(p, None).unwrap()
5274 .binding_signature().typ();
5275 assert_eq!(typ, SignatureType::PositiveCertification,
5276 "{:#?}", cert);
5277
5278 let revoked = cert.revocation_status(p, None);
5279 if direct_revoked {
5280 assert_match!(RevocationStatus::Revoked(_) = revoked,
5281 "{:#?}", cert);
5282 } else {
5283 assert_eq!(revoked, RevocationStatus::NotAsFarAsWeKnow,
5284 "{:#?}", cert);
5285 }
5286
5287 for userid in cert.userids().with_policy(p, None) {
5288 let typ = userid.binding_signature().typ();
5289 assert_eq!(typ, SignatureType::PositiveCertification,
5290 "{:#?}", cert);
5291
5292 let revoked = userid.revocation_status();
5293 if userid_revoked {
5294 assert_match!(RevocationStatus::Revoked(_) = revoked);
5295 } else {
5296 assert_eq!(RevocationStatus::NotAsFarAsWeKnow, revoked,
5297 "{:#?}", cert);
5298 }
5299 }
5300
5301 for subkey in cert.subkeys() {
5302 let typ = subkey.binding_signature(p, None).unwrap().typ();
5303 assert_eq!(typ, SignatureType::SubkeyBinding,
5304 "{:#?}", cert);
5305
5306 let revoked = subkey.revocation_status(p, None);
5307 if subkey_revoked {
5308 assert_match!(RevocationStatus::Revoked(_) = revoked);
5309 } else {
5310 assert_eq!(RevocationStatus::NotAsFarAsWeKnow, revoked,
5311 "{:#?}", cert);
5312 }
5313 }
5314 }
5315
5316 let cert = Cert::from_bytes(crate::tests::key("already-revoked.pgp")).unwrap();
5317 check(&cert, false, false, false);
5318
5319 let d = Cert::from_bytes(
5320 crate::tests::key("already-revoked-direct-revocation.pgp")).unwrap();
5321 check(&d, true, false, false);
5322
5323 check(&cert.clone().merge_public_and_secret(d.clone()).unwrap(), true, false, false);
5324 // Make sure the merge order does not matter.
5325 check(&d.clone().merge_public_and_secret(cert.clone()).unwrap(), true, false, false);
5326
5327 let u = Cert::from_bytes(
5328 crate::tests::key("already-revoked-userid-revocation.pgp")).unwrap();
5329 check(&u, false, true, false);
5330
5331 check(&cert.clone().merge_public_and_secret(u.clone()).unwrap(), false, true, false);
5332 check(&u.clone().merge_public_and_secret(cert.clone()).unwrap(), false, true, false);
5333
5334 let k = Cert::from_bytes(
5335 crate::tests::key("already-revoked-subkey-revocation.pgp")).unwrap();
5336 check(&k, false, false, true);
5337
5338 check(&cert.clone().merge_public_and_secret(k.clone()).unwrap(), false, false, true);
5339 check(&k.clone().merge_public_and_secret(cert.clone()).unwrap(), false, false, true);
5340
5341 // direct and user id revocation.
5342 check(&d.clone().merge_public_and_secret(u.clone()).unwrap(), true, true, false);
5343 check(&u.clone().merge_public_and_secret(d.clone()).unwrap(), true, true, false);
5344
5345 // direct and subkey revocation.
5346 check(&d.clone().merge_public_and_secret(k.clone()).unwrap(), true, false, true);
5347 check(&k.clone().merge_public_and_secret(d.clone()).unwrap(), true, false, true);
5348
5349 // user id and subkey revocation.
5350 check(&u.clone().merge_public_and_secret(k.clone()).unwrap(), false, true, true);
5351 check(&k.clone().merge_public_and_secret(u.clone()).unwrap(), false, true, true);
5352
5353 // direct, user id and subkey revocation.
5354 check(&d.clone().merge_public_and_secret(u.clone().merge_public_and_secret(k.clone()).unwrap()).unwrap(),
5355 true, true, true);
5356 check(&d.clone().merge_public_and_secret(k.clone().merge_public_and_secret(u.clone()).unwrap()).unwrap(),
5357 true, true, true);
5358 }
5359
5360 #[test]
5361 fn revoke() {
5362 let p = &P::new();
5363
5364 let (cert, _) = CertBuilder::general_purpose(Some("Test"))
5365 .generate().unwrap();
5366 assert_eq!(RevocationStatus::NotAsFarAsWeKnow,
5367 cert.revocation_status(p, None));
5368
5369 let mut keypair = cert.primary_key().key().clone().parts_into_secret()
5370 .unwrap().into_keypair().unwrap();
5371
5372 let sig = CertRevocationBuilder::new()
5373 .set_reason_for_revocation(
5374 ReasonForRevocation::KeyCompromised,
5375 b"It was the maid :/").unwrap()
5376 .build(&mut keypair, &cert, None)
5377 .unwrap();
5378 assert_eq!(sig.typ(), SignatureType::KeyRevocation);
5379 assert_eq!(sig.issuers().collect::<Vec<_>>(),
5380 vec![ &cert.keyid() ]);
5381 assert_eq!(sig.issuer_fingerprints().collect::<Vec<_>>(),
5382 vec![ &cert.fingerprint() ]);
5383
5384 let cert = cert.insert_packets(sig).unwrap().0;
5385 assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, None));
5386
5387
5388 // Have other revoke cert.
5389 let (other, _) = CertBuilder::general_purpose(Some("Test 2"))
5390 .generate().unwrap();
5391
5392 let mut keypair = other.primary_key().key().clone().parts_into_secret()
5393 .unwrap().into_keypair().unwrap();
5394
5395 let sig = CertRevocationBuilder::new()
5396 .set_reason_for_revocation(
5397 ReasonForRevocation::KeyCompromised,
5398 b"It was the maid :/").unwrap()
5399 .build(&mut keypair, &cert, None)
5400 .unwrap();
5401
5402 assert_eq!(sig.typ(), SignatureType::KeyRevocation);
5403 assert_eq!(sig.issuers().collect::<Vec<_>>(),
5404 vec![ &other.keyid() ]);
5405 assert_eq!(sig.issuer_fingerprints().collect::<Vec<_>>(),
5406 vec![ &other.fingerprint() ]);
5407 }
5408
5409 #[test]
5410 fn revoke_subkey() {
5411 let p = &P::new();
5412 let (cert, _) = CertBuilder::new()
5413 .add_transport_encryption_subkey()
5414 .generate().unwrap();
5415
5416 let sig = {
5417 let subkey = cert.subkeys().next().unwrap();
5418 assert_eq!(RevocationStatus::NotAsFarAsWeKnow,
5419 subkey.revocation_status(p, None));
5420
5421 let mut keypair = cert.primary_key().key().clone().parts_into_secret()
5422 .unwrap().into_keypair().unwrap();
5423 SubkeyRevocationBuilder::new()
5424 .set_reason_for_revocation(
5425 ReasonForRevocation::UIDRetired,
5426 b"It was the maid :/").unwrap()
5427 .build(&mut keypair, &cert, subkey.key(), None)
5428 .unwrap()
5429 };
5430 assert_eq!(sig.typ(), SignatureType::SubkeyRevocation);
5431 let cert = cert.insert_packets(sig).unwrap().0;
5432 assert_eq!(RevocationStatus::NotAsFarAsWeKnow,
5433 cert.revocation_status(p, None));
5434
5435 let subkey = cert.subkeys().next().unwrap();
5436 assert_match!(RevocationStatus::Revoked(_)
5437 = subkey.revocation_status(p, None));
5438 }
5439
5440 #[test]
5441 fn revoke_uid() {
5442 let p = &P::new();
5443 let (cert, _) = CertBuilder::new()
5444 .add_userid("Test1")
5445 .add_userid("Test2")
5446 .generate().unwrap();
5447
5448 let sig = {
5449 let uid = cert.userids().with_policy(p, None).nth(1).unwrap();
5450 assert_eq!(RevocationStatus::NotAsFarAsWeKnow, uid.revocation_status());
5451
5452 let mut keypair = cert.primary_key().key().clone().parts_into_secret()
5453 .unwrap().into_keypair().unwrap();
5454 UserIDRevocationBuilder::new()
5455 .set_reason_for_revocation(
5456 ReasonForRevocation::UIDRetired,
5457 b"It was the maid :/").unwrap()
5458 .build(&mut keypair, &cert, uid.userid(), None)
5459 .unwrap()
5460 };
5461 assert_eq!(sig.typ(), SignatureType::CertificationRevocation);
5462 let cert = cert.insert_packets(sig).unwrap().0;
5463 assert_eq!(RevocationStatus::NotAsFarAsWeKnow,
5464 cert.revocation_status(p, None));
5465
5466 let uid = cert.userids().with_policy(p, None).nth(1).unwrap();
5467 assert_match!(RevocationStatus::Revoked(_) = uid.revocation_status());
5468 }
5469
5470 #[test]
5471 fn key_revoked() {
5472 use crate::types::Features;
5473 use crate::packet::key::Key6;
5474 use rand::{rng, Rng, distr::Open01};
5475
5476 let p = &P::new();
5477
5478 /*
5479 * t1: 1st binding sig ctime
5480 * t2: soft rev sig ctime
5481 * t3: 2nd binding sig ctime
5482 * t4: hard rev sig ctime
5483 *
5484 * [0,t1): invalid, but not revoked
5485 * [t1,t2): valid (not revocations)
5486 * [t2,t3): revoked (soft revocation)
5487 * [t3,t4): valid again (new self sig)
5488 * [t4,inf): hard revocation (hard revocation)
5489 *
5490 * Once the hard revocation is merged, then the Cert is
5491 * considered revoked at all times.
5492 */
5493 let t1 = time::UNIX_EPOCH + time::Duration::new(946681200, 0); // 2000-1-1
5494 let t2 = time::UNIX_EPOCH + time::Duration::new(978303600, 0); // 2001-1-1
5495 let t3 = time::UNIX_EPOCH + time::Duration::new(1009839600, 0); // 2002-1-1
5496 let t4 = time::UNIX_EPOCH + time::Duration::new(1041375600, 0); // 2003-1-1
5497
5498 let mut key: key::SecretKey
5499 = Key6::generate_ecc(true, Curve::Ed25519).unwrap().into();
5500 key.set_creation_time(t1).unwrap();
5501 let mut pair = key.clone().into_keypair().unwrap();
5502 let (bind1, rev1, bind2, rev2) = {
5503 let bind1 = signature::SignatureBuilder::new(SignatureType::DirectKey)
5504 .set_features(Features::sequoia()).unwrap()
5505 .set_key_flags(KeyFlags::empty()).unwrap()
5506 .set_signature_creation_time(t1).unwrap()
5507 .set_key_validity_period(Some(time::Duration::new(10 * 52 * 7 * 24 * 60 * 60, 0))).unwrap()
5508 .set_preferred_hash_algorithms(vec![HashAlgorithm::SHA512]).unwrap()
5509 .sign_direct_key(&mut pair, key.parts_as_public()).unwrap();
5510
5511 let rev1 = signature::SignatureBuilder::new(SignatureType::KeyRevocation)
5512 .set_signature_creation_time(t2).unwrap()
5513 .set_reason_for_revocation(ReasonForRevocation::KeySuperseded,
5514 &b""[..]).unwrap()
5515 .sign_direct_key(&mut pair, key.parts_as_public()).unwrap();
5516
5517 let bind2 = signature::SignatureBuilder::new(SignatureType::DirectKey)
5518 .set_features(Features::sequoia()).unwrap()
5519 .set_key_flags(KeyFlags::empty()).unwrap()
5520 .set_signature_creation_time(t3).unwrap()
5521 .set_key_validity_period(Some(time::Duration::new(10 * 52 * 7 * 24 * 60 * 60, 0))).unwrap()
5522 .set_preferred_hash_algorithms(vec![HashAlgorithm::SHA512]).unwrap()
5523 .sign_direct_key(&mut pair, key.parts_as_public()).unwrap();
5524
5525 let rev2 = signature::SignatureBuilder::new(SignatureType::KeyRevocation)
5526 .set_signature_creation_time(t4).unwrap()
5527 .set_reason_for_revocation(ReasonForRevocation::KeyCompromised,
5528 &b""[..]).unwrap()
5529 .sign_direct_key(&mut pair, key.parts_as_public()).unwrap();
5530
5531 (bind1, rev1, bind2, rev2)
5532 };
5533 let pk : key::PublicKey = key.into();
5534 let cert = Cert::try_from(vec![
5535 pk.into(),
5536 bind1.into(),
5537 bind2.into(),
5538 rev1.into()
5539 ]).unwrap();
5540
5541 let f1: f32 = rng().sample(Open01);
5542 let f2: f32 = rng().sample(Open01);
5543 let f3: f32 = rng().sample(Open01);
5544 let f4: f32 = rng().sample(Open01);
5545 let te1 = t1 - time::Duration::new((60. * 60. * 24. * 300.0 * f1) as u64, 0);
5546 let t12 = t1 + time::Duration::new((60. * 60. * 24. * 300.0 * f2) as u64, 0);
5547 let t23 = t2 + time::Duration::new((60. * 60. * 24. * 300.0 * f3) as u64, 0);
5548 let t34 = t3 + time::Duration::new((60. * 60. * 24. * 300.0 * f4) as u64, 0);
5549
5550 assert_eq!(cert.revocation_status(p, te1), RevocationStatus::NotAsFarAsWeKnow);
5551 assert_eq!(cert.revocation_status(p, t12), RevocationStatus::NotAsFarAsWeKnow);
5552 assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, t23));
5553 assert_eq!(cert.revocation_status(p, t34), RevocationStatus::NotAsFarAsWeKnow);
5554
5555 // Merge in the hard revocation.
5556 let cert = cert.insert_packets(rev2).unwrap().0;
5557 assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, te1));
5558 assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, t12));
5559 assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, t23));
5560 assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, t34));
5561 assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, t4));
5562 assert_match!(RevocationStatus::Revoked(_)
5563 = cert.revocation_status(p, crate::now()));
5564 }
5565
5566 #[test]
5567 fn key_revoked2() {
5568 tracer!(true, "cert_revoked2", 0);
5569
5570 let p = &P::new();
5571
5572 fn cert_revoked<T>(p: &dyn Policy, cert: &Cert, t: T) -> bool
5573 where T: Into<Option<time::SystemTime>>
5574 {
5575 !matches!(
5576 cert.revocation_status(p, t),
5577 RevocationStatus::NotAsFarAsWeKnow
5578 )
5579 }
5580
5581 fn subkey_revoked<T>(p: &dyn Policy, cert: &Cert, t: T) -> bool
5582 where T: Into<Option<time::SystemTime>>
5583 {
5584 !matches!(
5585 cert.subkeys().next().unwrap().bundle().revocation_status(p, t),
5586 RevocationStatus::NotAsFarAsWeKnow
5587 )
5588 }
5589
5590 let tests : [(&str, Box<dyn Fn(&dyn Policy, &Cert, _) -> bool>); 2] = [
5591 ("cert", Box::new(cert_revoked)),
5592 ("subkey", Box::new(subkey_revoked)),
5593 ];
5594
5595 for (f, revoked) in tests.iter()
5596 {
5597 t!("Checking {} revocation", f);
5598
5599 t!("Normal key");
5600 let cert = Cert::from_bytes(
5601 crate::tests::key(
5602 &format!("really-revoked-{}-0-public.pgp", f))).unwrap();
5603 let selfsig0 = cert.primary_key().with_policy(p, None).unwrap()
5604 .binding_signature().signature_creation_time().unwrap();
5605
5606 assert!(!revoked(p, &cert, Some(selfsig0)));
5607 assert!(!revoked(p, &cert, None));
5608
5609 t!("Soft revocation");
5610 let cert = cert.merge_public_and_secret(
5611 Cert::from_bytes(
5612 crate::tests::key(
5613 &format!("really-revoked-{}-1-soft-revocation.pgp", f))
5614 ).unwrap()).unwrap();
5615 // A soft revocation made after `t` is ignored when
5616 // determining whether the key is revoked at time `t`.
5617 assert!(!revoked(p, &cert, Some(selfsig0)));
5618 assert!(revoked(p, &cert, None));
5619
5620 t!("New self signature");
5621 let cert = cert.merge_public_and_secret(
5622 Cert::from_bytes(
5623 crate::tests::key(
5624 &format!("really-revoked-{}-2-new-self-sig.pgp", f))
5625 ).unwrap()).unwrap();
5626 assert!(!revoked(p, &cert, Some(selfsig0)));
5627 // Newer self-sig override older soft revocations.
5628 assert!(!revoked(p, &cert, None));
5629
5630 t!("Hard revocation");
5631 let cert = cert.merge_public_and_secret(
5632 Cert::from_bytes(
5633 crate::tests::key(
5634 &format!("really-revoked-{}-3-hard-revocation.pgp", f))
5635 ).unwrap()).unwrap();
5636 // Hard revocations trump all.
5637 assert!(revoked(p, &cert, Some(selfsig0)));
5638 assert!(revoked(p, &cert, None));
5639
5640 t!("New self signature");
5641 let cert = cert.merge_public_and_secret(
5642 Cert::from_bytes(
5643 crate::tests::key(
5644 &format!("really-revoked-{}-4-new-self-sig.pgp", f))
5645 ).unwrap()).unwrap();
5646 assert!(revoked(p, &cert, Some(selfsig0)));
5647 assert!(revoked(p, &cert, None));
5648 }
5649 }
5650
5651 #[test]
5652 fn userid_revoked2() {
5653 fn check_userids<T>(p: &dyn Policy, cert: &Cert, revoked: bool, t: T)
5654 where T: Into<Option<time::SystemTime>>, T: Copy
5655 {
5656 assert_match!(RevocationStatus::NotAsFarAsWeKnow
5657 = cert.revocation_status(p, None));
5658
5659 let mut slim_shady = false;
5660 let mut eminem = false;
5661 for b in cert.userids().with_policy(p, t) {
5662 if b.userid().value() == b"Slim Shady" {
5663 assert!(!slim_shady);
5664 slim_shady = true;
5665
5666 if revoked {
5667 assert_match!(RevocationStatus::Revoked(_)
5668 = b.revocation_status());
5669 } else {
5670 assert_match!(RevocationStatus::NotAsFarAsWeKnow
5671 = b.revocation_status());
5672 }
5673 } else {
5674 assert!(!eminem);
5675 eminem = true;
5676
5677 assert_match!(RevocationStatus::NotAsFarAsWeKnow
5678 = b.revocation_status());
5679 }
5680 }
5681
5682 assert!(slim_shady);
5683 assert!(eminem);
5684 }
5685
5686 fn check_uas<T>(p: &dyn Policy, cert: &Cert, revoked: bool, t: T)
5687 where T: Into<Option<time::SystemTime>>, T: Copy
5688 {
5689 assert_match!(RevocationStatus::NotAsFarAsWeKnow
5690 = cert.revocation_status(p, None));
5691
5692 assert_eq!(cert.user_attributes().count(), 1);
5693 let ua = cert.user_attributes().next().unwrap();
5694 if revoked {
5695 assert_match!(RevocationStatus::Revoked(_)
5696 = ua.revocation_status(p, t));
5697 } else {
5698 assert_match!(RevocationStatus::NotAsFarAsWeKnow
5699 = ua.revocation_status(p, t));
5700 }
5701 }
5702
5703 tracer!(true, "userid_revoked2", 0);
5704
5705 let p = &P::new();
5706 let tests : [(&str, Box<dyn Fn(&dyn Policy, &Cert, bool, _)>); 2] = [
5707 ("userid", Box::new(check_userids)),
5708 ("user-attribute", Box::new(check_uas)),
5709 ];
5710
5711 for (f, check) in tests.iter()
5712 {
5713 t!("Checking {} revocation", f);
5714
5715 t!("Normal key");
5716 let cert = Cert::from_bytes(
5717 crate::tests::key(
5718 &format!("really-revoked-{}-0-public.pgp", f))).unwrap();
5719
5720 let now = crate::now();
5721 let selfsig0
5722 = cert.userids().with_policy(p, now).map(|b| {
5723 b.binding_signature().signature_creation_time().unwrap()
5724 })
5725 .max().unwrap();
5726
5727 check(p, &cert, false, selfsig0);
5728 check(p, &cert, false, now);
5729
5730 // A soft-revocation.
5731 let cert = cert.merge_public_and_secret(
5732 Cert::from_bytes(
5733 crate::tests::key(
5734 &format!("really-revoked-{}-1-soft-revocation.pgp", f))
5735 ).unwrap()).unwrap();
5736
5737 check(p, &cert, false, selfsig0);
5738 check(p, &cert, true, now);
5739
5740 // A new self signature. This should override the soft-revocation.
5741 let cert = cert.merge_public_and_secret(
5742 Cert::from_bytes(
5743 crate::tests::key(
5744 &format!("really-revoked-{}-2-new-self-sig.pgp", f))
5745 ).unwrap()).unwrap();
5746
5747 check(p, &cert, false, selfsig0);
5748 check(p, &cert, false, now);
5749
5750 // A hard revocation. Unlike for Certs, this does NOT trump
5751 // everything.
5752 let cert = cert.merge_public_and_secret(
5753 Cert::from_bytes(
5754 crate::tests::key(
5755 &format!("really-revoked-{}-3-hard-revocation.pgp", f))
5756 ).unwrap()).unwrap();
5757
5758 check(p, &cert, false, selfsig0);
5759 check(p, &cert, true, now);
5760
5761 // A newer self signature.
5762 let cert = cert.merge_public_and_secret(
5763 Cert::from_bytes(
5764 crate::tests::key(
5765 &format!("really-revoked-{}-4-new-self-sig.pgp", f))
5766 ).unwrap()).unwrap();
5767
5768 check(p, &cert, false, selfsig0);
5769 check(p, &cert, false, now);
5770 }
5771 }
5772
5773 #[test]
5774 fn unrevoked() {
5775 let p = &P::new();
5776 let cert =
5777 Cert::from_bytes(crate::tests::key("un-revoked-userid.pgp")).unwrap();
5778
5779 for uid in cert.userids().with_policy(p, None) {
5780 assert_eq!(uid.revocation_status(), RevocationStatus::NotAsFarAsWeKnow);
5781 }
5782 }
5783
5784 #[test]
5785 fn is_tsk() {
5786 let cert = Cert::from_bytes(
5787 crate::tests::key("already-revoked.pgp")).unwrap();
5788 assert!(! cert.is_tsk());
5789
5790 let cert = Cert::from_bytes(
5791 crate::tests::key("already-revoked-private.pgp")).unwrap();
5792 assert!(cert.is_tsk());
5793 }
5794
5795 #[test]
5796 fn export_only_exports_public_key() {
5797 let cert = Cert::from_bytes(
5798 crate::tests::key("testy-new-private.pgp")).unwrap();
5799 assert!(cert.is_tsk());
5800
5801 let mut v = Vec::new();
5802 cert.serialize(&mut v).unwrap();
5803 let cert = Cert::from_bytes(&v).unwrap();
5804 assert!(! cert.is_tsk());
5805 }
5806
5807 // Make sure that when merging two Certs, the primary key and
5808 // subkeys with and without a private key are merged.
5809 #[test]
5810 fn public_private_merge() {
5811 let (tsk, _) = CertBuilder::general_purpose(Some("foo@example.com"))
5812 .generate().unwrap();
5813 // tsk is now a cert, but it still has its private bits.
5814 assert!(tsk.primary.key().has_secret());
5815 assert!(tsk.is_tsk());
5816 let subkey_count = tsk.subkeys().count();
5817 assert!(subkey_count > 0);
5818 assert!(tsk.subkeys().all(|k| k.key().has_secret()));
5819
5820 // This will write out the tsk as a cert, i.e., without any
5821 // private bits.
5822 let mut cert_bytes = Vec::new();
5823 tsk.serialize(&mut cert_bytes).unwrap();
5824
5825 // Reading it back in, the private bits have been stripped.
5826 let cert = Cert::from_bytes(&cert_bytes[..]).unwrap();
5827 assert!(! cert.primary.key().has_secret());
5828 assert!(!cert.is_tsk());
5829 assert!(cert.subkeys().all(|k| ! k.key().has_secret()));
5830
5831 let merge1 = cert.clone().merge_public_and_secret(tsk.clone()).unwrap();
5832 assert!(merge1.is_tsk());
5833 assert!(merge1.primary.key().has_secret());
5834 assert_eq!(merge1.subkeys().count(), subkey_count);
5835 assert!(merge1.subkeys().all(|k| k.key().has_secret()));
5836
5837 let merge2 = tsk.clone().merge_public_and_secret(cert.clone()).unwrap();
5838 assert!(merge2.is_tsk());
5839 assert!(merge2.primary.key().has_secret());
5840 assert_eq!(merge2.subkeys().count(), subkey_count);
5841 assert!(merge2.subkeys().all(|k| k.key().has_secret()));
5842 }
5843
5844 #[test]
5845 fn issue_120() {
5846 let cert = "
5847-----BEGIN PGP ARMORED FILE-----
5848
5849xcBNBFoVcvoBCACykTKOJddF8SSUAfCDHk86cNTaYnjCoy72rMgWJsrMLnz/V16B
5850J9M7l6nrQ0JMnH2Du02A3w+kNb5q97IZ/M6NkqOOl7uqjyRGPV+XKwt0G5mN/ovg
58518630BZAYS3QzavYf3tni9aikiGH+zTFX5pynTNfYRXNBof3Xfzl92yad2bIt4ITD
5852NfKPvHRko/tqWbclzzEn72gGVggt1/k/0dKhfsGzNogHxg4GIQ/jR/XcqbDFR3RC
5853/JJjnTOUPGsC1y82Xlu8udWBVn5mlDyxkad5laUpWWg17anvczEAyx4TTOVItLSu
585443iPdKHSs9vMXWYID0bg913VusZ2Ofv690nDABEBAAHNJFRlc3R5IE1jVGVzdGZh
5855Y2UgPHRlc3R5QGV4YW1wbGUub3JnPsLAlAQTAQgAPhYhBD6Id8h3J0aSl1GJ9dA/
5856b4ZSJv6LBQJaFXL6AhsDBQkDwmcABQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJ
5857ENA/b4ZSJv6Lxo8H/1XMt+Nqa6e0SG/up3ypKe5nplA0p/9j/s2EIsP8S8uPUd+c
5858WS17XOmPwkNDmHeL3J6hzwL74NlYSLEtyf7WoOV74xAKQA9WkqaKPHCtpll8aFWA
5859ktQDLWTPeKuUuSlobAoRtO17ZmheSQzmm7JYt4Ahkxt3agqGT05OsaAey6nIKqpq
5860ArokvdHTZ7AFZeSJIWmuCoT9M1lo3LAtLnRGOhBMJ5dDIeOwflJwNBXlJVi4mDPK
5861+fumV0MbSPvZd1/ivFjSpQyudWWtv1R1nAK7+a4CPTGxPvAQkLtRsL/V+Q7F3BJG
5862jAn4QVx8p4t3NOPuNgcoZpLBE3sc4Nfs5/CphMLHwE0EWhVy+gEIALSpjYD+tuWC
5863rj6FGP6crQjQzVlH+7axoM1ooTwiPs4fzzt2iLw3CJyDUviM5F9ZBQTei635RsAR
5864a/CJTSQYAEU5yXXxhoe0OtwnuvsBSvVT7Fox3pkfNTQmwMvkEbodhfKpqBbDKCL8
5865f5A8Bb7aISsLf0XRHWDkHVqlz8LnOR3f44wEWiTeIxLc8S1QtwX/ExyW47oPsjs9
5866ShCmwfSpcngH/vGBRTO7WeI54xcAtKSm/20B/MgrUl5qFo17kUWot2C6KjuZKkHk
58673WZmJwQz+6rTB11w4AXt8vKkptYQCkfat2FydGpgRO5dVg6aWNJefOJNkC7MmlzC
5868ZrrAK8FJ6jcAEQEAAcLAdgQYAQgAIBYhBD6Id8h3J0aSl1GJ9dA/b4ZSJv6LBQJa
5869FXL6AhsMAAoJENA/b4ZSJv6Lt7kH/jPr5wg8lcamuLj4lydYiLttvvTtDTlD1TL+
5870IfwVARB/ruoerlEDr0zX1t3DCEcvJDiZfOqJbXtHt70+7NzFXrYxfaNFmikMgSQT
5871XqHrMQho4qpseVOeJPWGzGOcrxCdw/ZgrWbkDlAU5KaIvk+M4wFPivjbtW2Ro2/F
5872J4I/ZHhJlIPmM+hUErHC103b08pBENXDQlXDma7LijH5kWhyfF2Ji7Ft0EjghBaW
5873AeGalQHjc5kAZu5R76Mwt06MEQ/HL1pIvufTFxkr/SzIv8Ih7Kexb0IrybmfD351
5874Pu1xwz57O4zo1VYf6TqHJzVC3OMvMUM2hhdecMUe5x6GorNaj6g=
5875=1Vzu
5876-----END PGP ARMORED FILE-----
5877";
5878 assert!(Cert::from_bytes(cert).is_err());
5879 }
5880
5881 #[test]
5882 fn missing_uids() {
5883 let (cert, _) = CertBuilder::new()
5884 .add_userid("test1@example.com")
5885 .add_userid("test2@example.com")
5886 .add_transport_encryption_subkey()
5887 .add_certification_subkey()
5888 .generate().unwrap();
5889 assert_eq!(cert.subkeys().count(), 2);
5890 let pile = cert
5891 .into_packet_pile()
5892 .into_children()
5893 .filter(|pkt| {
5894 match pkt {
5895 &Packet::PublicKey(_) | &Packet::PublicSubkey(_)
5896 | &Packet::SecretKey(_) | &Packet::SecretSubkey(_) => true,
5897 &Packet::Signature(ref sig) => {
5898 sig.typ() == SignatureType::DirectKey
5899 || sig.typ() == SignatureType::SubkeyBinding
5900 }
5901 e => {
5902 eprintln!("{:?}", e);
5903 false
5904 }
5905 }
5906 })
5907 .collect::<Vec<_>>();
5908 eprintln!("parse back");
5909 let cert = Cert::try_from(pile).unwrap();
5910
5911 assert_eq!(cert.subkeys().count(), 2);
5912 }
5913
5914 #[test]
5915 fn signature_order() {
5916 let p = &P::new();
5917 let neal = Cert::from_bytes(crate::tests::key("neal.pgp")).unwrap();
5918
5919 // This test is useless if we don't have some lists with more
5920 // than one signature.
5921 let mut cmps = 0;
5922
5923 for uid in neal.userids() {
5924 for sigs in [
5925 uid.self_signatures().collect::<Vec<_>>(),
5926 uid.certifications().collect::<Vec<_>>(),
5927 uid.self_revocations().collect::<Vec<_>>(),
5928 uid.other_revocations().collect::<Vec<_>>()
5929 ].iter() {
5930 for sigs in sigs.windows(2) {
5931 cmps += 1;
5932 assert!(sigs[0].signature_creation_time()
5933 >= sigs[1].signature_creation_time());
5934 }
5935 }
5936
5937 // Make sure we return the most recent first.
5938 assert_eq!(uid.self_signatures().next().unwrap(),
5939 uid.binding_signature(p, None).unwrap());
5940 }
5941
5942 assert!(cmps > 0);
5943 }
5944
5945 #[test]
5946 fn cert_reject_keyrings() {
5947 let mut keyring = Vec::new();
5948 keyring.extend_from_slice(crate::tests::key("neal.pgp"));
5949 keyring.extend_from_slice(crate::tests::key("neal.pgp"));
5950 assert!(Cert::from_bytes(&keyring).is_err());
5951 }
5952
5953 #[test]
5954 fn primary_userid() {
5955 // 'really-revoked-userid' has two user ids. One of them is
5956 // revoked and then restored. Neither of the user ids has the
5957 // primary userid bit set.
5958 //
5959 // This test makes sure that Cert::primary_userid prefers
5960 // unrevoked user ids to revoked user ids, even if the latter
5961 // have newer self signatures.
5962
5963 let p = &P::new();
5964 let cert = Cert::from_bytes(
5965 crate::tests::key("really-revoked-userid-0-public.pgp")).unwrap();
5966
5967 let now = crate::now();
5968 let selfsig0
5969 = cert.userids().with_policy(p, now).map(|b| {
5970 b.binding_signature().signature_creation_time().unwrap()
5971 })
5972 .max().unwrap();
5973
5974 // The self-sig for:
5975 //
5976 // Slim Shady: 2019-09-14T14:21
5977 // Eminem: 2019-09-14T14:22
5978 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
5979 .primary_userid().unwrap().userid().value(),
5980 b"Eminem");
5981 assert_eq!(cert.with_policy(p, now).unwrap()
5982 .primary_userid().unwrap().userid().value(),
5983 b"Eminem");
5984
5985 // A soft-revocation for "Slim Shady".
5986 let cert = cert.merge_public_and_secret(
5987 Cert::from_bytes(
5988 crate::tests::key("really-revoked-userid-1-soft-revocation.pgp")
5989 ).unwrap()).unwrap();
5990
5991 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
5992 .primary_userid().unwrap().userid().value(),
5993 b"Eminem");
5994 assert_eq!(cert.with_policy(p, now).unwrap()
5995 .primary_userid().unwrap().userid().value(),
5996 b"Eminem");
5997
5998 // A new self signature for "Slim Shady". This should
5999 // override the soft-revocation.
6000 let cert = cert.merge_public_and_secret(
6001 Cert::from_bytes(
6002 crate::tests::key("really-revoked-userid-2-new-self-sig.pgp")
6003 ).unwrap()).unwrap();
6004
6005 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6006 .primary_userid().unwrap().userid().value(),
6007 b"Eminem");
6008 assert_eq!(cert.with_policy(p, now).unwrap()
6009 .primary_userid().unwrap().userid().value(),
6010 b"Slim Shady");
6011
6012 // A hard revocation for "Slim Shady".
6013 let cert = cert.merge_public_and_secret(
6014 Cert::from_bytes(
6015 crate::tests::key("really-revoked-userid-3-hard-revocation.pgp")
6016 ).unwrap()).unwrap();
6017
6018 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6019 .primary_userid().unwrap().userid().value(),
6020 b"Eminem");
6021 assert_eq!(cert.with_policy(p, now).unwrap()
6022 .primary_userid().unwrap().userid().value(),
6023 b"Eminem");
6024
6025 // A newer self signature for "Slim Shady". Unlike for Certs, this
6026 // does NOT trump everything.
6027 let cert = cert.merge_public_and_secret(
6028 Cert::from_bytes(
6029 crate::tests::key("really-revoked-userid-4-new-self-sig.pgp")
6030 ).unwrap()).unwrap();
6031
6032 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6033 .primary_userid().unwrap().userid().value(),
6034 b"Eminem");
6035 assert_eq!(cert.with_policy(p, now).unwrap()
6036 .primary_userid().unwrap().userid().value(),
6037 b"Slim Shady");
6038
6039 // Play with the primary user id flag.
6040
6041 let cert = Cert::from_bytes(
6042 crate::tests::key("primary-key-0-public.pgp")).unwrap();
6043 let selfsig0
6044 = cert.userids().with_policy(p, now).map(|b| {
6045 b.binding_signature().signature_creation_time().unwrap()
6046 })
6047 .max().unwrap();
6048
6049 // There is only a single User ID.
6050 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6051 .primary_userid().unwrap().userid().value(),
6052 b"aaaaa");
6053 assert_eq!(cert.with_policy(p, now).unwrap()
6054 .primary_userid().unwrap().userid().value(),
6055 b"aaaaa");
6056
6057
6058 // Add a second user id. Since neither is marked primary, the
6059 // newer one should be considered primary.
6060 let cert = cert.merge_public_and_secret(
6061 Cert::from_bytes(
6062 crate::tests::key("primary-key-1-add-userid-bbbbb.pgp")
6063 ).unwrap()).unwrap();
6064
6065 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6066 .primary_userid().unwrap().userid().value(),
6067 b"aaaaa");
6068 assert_eq!(cert.with_policy(p, now).unwrap()
6069 .primary_userid().unwrap().userid().value(),
6070 b"bbbbb");
6071
6072 // Mark aaaaa as primary. It is now primary and the newest one.
6073 let cert = cert.merge_public_and_secret(
6074 Cert::from_bytes(
6075 crate::tests::key("primary-key-2-make-aaaaa-primary.pgp")
6076 ).unwrap()).unwrap();
6077
6078 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6079 .primary_userid().unwrap().userid().value(),
6080 b"aaaaa");
6081 assert_eq!(cert.with_policy(p, now).unwrap()
6082 .primary_userid().unwrap().userid().value(),
6083 b"aaaaa");
6084
6085 // Update the preferences on bbbbb. It is now the newest, but
6086 // it is not marked as primary.
6087 let cert = cert.merge_public_and_secret(
6088 Cert::from_bytes(
6089 crate::tests::key("primary-key-3-make-bbbbb-new-self-sig.pgp")
6090 ).unwrap()).unwrap();
6091
6092 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6093 .primary_userid().unwrap().userid().value(),
6094 b"aaaaa");
6095 assert_eq!(cert.with_policy(p, now).unwrap()
6096 .primary_userid().unwrap().userid().value(),
6097 b"aaaaa");
6098
6099 // Mark bbbbb as primary. It is now the newest and marked as
6100 // primary.
6101 let cert = cert.merge_public_and_secret(
6102 Cert::from_bytes(
6103 crate::tests::key("primary-key-4-make-bbbbb-primary.pgp")
6104 ).unwrap()).unwrap();
6105
6106 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6107 .primary_userid().unwrap().userid().value(),
6108 b"aaaaa");
6109 assert_eq!(cert.with_policy(p, now).unwrap()
6110 .primary_userid().unwrap().userid().value(),
6111 b"bbbbb");
6112
6113 // Update the preferences on aaaaa. It is now has the newest
6114 // self sig, but that self sig does not say that it is
6115 // primary.
6116 let cert = cert.merge_public_and_secret(
6117 Cert::from_bytes(
6118 crate::tests::key("primary-key-5-make-aaaaa-self-sig.pgp")
6119 ).unwrap()).unwrap();
6120
6121 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6122 .primary_userid().unwrap().userid().value(),
6123 b"aaaaa");
6124 assert_eq!(cert.with_policy(p, now).unwrap()
6125 .primary_userid().unwrap().userid().value(),
6126 b"bbbbb");
6127
6128 // Hard revoke aaaaa. Unlike with Certs, a hard revocation is
6129 // not treated specially.
6130 let cert = cert.merge_public_and_secret(
6131 Cert::from_bytes(
6132 crate::tests::key("primary-key-6-revoked-aaaaa.pgp")
6133 ).unwrap()).unwrap();
6134
6135 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6136 .primary_userid().unwrap().userid().value(),
6137 b"aaaaa");
6138 assert_eq!(cert.with_policy(p, now).unwrap()
6139 .primary_userid().unwrap().userid().value(),
6140 b"bbbbb");
6141 }
6142
6143 #[test]
6144 fn binding_signature_lookup() {
6145 // Check that searching for the right binding signature works
6146 // even when there are signatures with the same time.
6147
6148 use crate::types::Features;
6149 use crate::packet::key::Key6;
6150
6151 let p = &P::new();
6152
6153 let a_sec = time::Duration::new(1, 0);
6154 let time_zero = time::UNIX_EPOCH;
6155
6156 let t1 = time::UNIX_EPOCH + time::Duration::new(946681200, 0); // 2000-1-1
6157 let t2 = time::UNIX_EPOCH + time::Duration::new(978303600, 0); // 2001-1-1
6158 let t3 = time::UNIX_EPOCH + time::Duration::new(1009839600, 0); // 2002-1-1
6159 let t4 = time::UNIX_EPOCH + time::Duration::new(1041375600, 0); // 2003-1-1
6160
6161 let mut key: key::SecretKey
6162 = Key6::generate_ecc(true, Curve::Ed25519).unwrap().into();
6163 key.set_creation_time(t1).unwrap();
6164 let mut pair = key.clone().into_keypair().unwrap();
6165 let pk : key::PublicKey = key.clone().into();
6166 let mut cert = Cert::try_from(vec![
6167 pk.into(),
6168 ]).unwrap();
6169 let uid: UserID = "foo@example.org".into();
6170 let sig = uid.certify(&mut pair, &cert,
6171 SignatureType::PositiveCertification,
6172 None,
6173 t1).unwrap();
6174 cert = cert.insert_packets(
6175 vec![Packet::from(uid), sig.into()]).unwrap().0;
6176
6177 const N: usize = 5;
6178 for (t, offset) in &[ (t2, 0), (t4, 0), (t3, 1 * N), (t1, 3 * N) ] {
6179 for i in 0..N {
6180 let binding = signature::SignatureBuilder::new(SignatureType::DirectKey)
6181 .set_features(Features::sequoia()).unwrap()
6182 .set_key_flags(KeyFlags::empty()).unwrap()
6183 .set_signature_creation_time(t1).unwrap()
6184 // Vary this...
6185 .set_key_validity_period(Some(
6186 time::Duration::new((1 + i as u64) * 24 * 60 * 60, 0)))
6187 .unwrap()
6188 .set_preferred_hash_algorithms(vec![HashAlgorithm::SHA512]).unwrap()
6189 .set_signature_creation_time(*t).unwrap()
6190 .sign_direct_key(&mut pair, key.parts_as_public()).unwrap();
6191
6192 let binding : Packet = binding.into();
6193
6194 cert = cert.insert_packets(binding).unwrap().0;
6195 // A time that matches multiple signatures.
6196 let direct_signatures =
6197 cert.primary_key().bundle().self_signatures()
6198 .collect::<Vec<_>>();
6199 assert_eq!(cert.primary_key().with_policy(p, *t).unwrap()
6200 .direct_key_signature().ok(),
6201 direct_signatures.get(*offset).cloned());
6202 // A time that doesn't match any signature.
6203 assert_eq!(cert.primary_key().with_policy(p, *t + a_sec).unwrap()
6204 .direct_key_signature().ok(),
6205 direct_signatures.get(*offset).cloned());
6206
6207 // The current time, which should use the first signature.
6208 assert_eq!(cert.primary_key().with_policy(p, None).unwrap()
6209 .direct_key_signature().ok(),
6210 direct_signatures.get(0).cloned());
6211
6212 // The beginning of time, which should return no
6213 // binding signatures.
6214 assert!(cert.primary_key().with_policy(p, time_zero).is_err());
6215 }
6216 }
6217 }
6218
6219 #[test]
6220 fn keysigning_party() {
6221 use crate::packet::signature;
6222
6223 for cs in &[ CipherSuite::Cv25519,
6224 CipherSuite::Cv448,
6225 CipherSuite::P256,
6226 CipherSuite::P384,
6227 CipherSuite::P521,
6228 CipherSuite::RSA2k ]
6229 {
6230 if cs.is_supported().is_err() {
6231 eprintln!("Skipping {:?} because it is not supported.", cs);
6232 continue;
6233 }
6234
6235 let (alice, _) = CertBuilder::new()
6236 .set_cipher_suite(*cs)
6237 .add_userid("alice@foo.com")
6238 .generate().unwrap();
6239
6240 let (bob, _) = CertBuilder::new()
6241 .set_cipher_suite(*cs)
6242 .add_userid("bob@bar.com")
6243 .add_signing_subkey()
6244 .generate().unwrap();
6245
6246 assert_eq!(bob.userids().len(), 1);
6247 let bob_userid_binding = bob.userids().next().unwrap();
6248 assert_eq!(bob_userid_binding.userid().value(), b"bob@bar.com");
6249
6250 let sig_template
6251 = signature::SignatureBuilder::new(SignatureType::GenericCertification)
6252 .set_trust_signature(255, 120)
6253 .unwrap();
6254
6255 // Have alice certify the binding "bob@bar.com" and bob's key.
6256 let alice_certifies_bob
6257 = bob_userid_binding.userid().bind(
6258 &mut alice.primary_key().key().clone().parts_into_secret()
6259 .unwrap().into_keypair().unwrap(),
6260 &bob,
6261 sig_template).unwrap();
6262
6263 let bob = bob.insert_packets(alice_certifies_bob.clone()).unwrap().0;
6264
6265 // Make sure the certification is merged, and put in the right
6266 // place.
6267 assert_eq!(bob.userids().len(), 1);
6268 let bob_userid_binding = bob.userids().next().unwrap();
6269 assert_eq!(bob_userid_binding.userid().value(), b"bob@bar.com");
6270
6271 // Canonicalizing Bob's cert without having Alice's key
6272 // has to resort to a heuristic to order third party
6273 // signatures. However, since we know the signature's
6274 // type (GenericCertification), we know that it can only
6275 // go to the only userid, so there is no ambiguity in this
6276 // case.
6277 assert_eq!(bob_userid_binding.certifications().collect::<Vec<_>>(),
6278 vec![&alice_certifies_bob]);
6279
6280 // Make sure the certification is correct.
6281 alice_certifies_bob
6282 .verify_userid_binding(alice.primary_key().key(),
6283 bob.primary_key().key(),
6284 bob_userid_binding.userid()).unwrap();
6285 }
6286 }
6287
6288 #[test]
6289 fn decrypt_encrypt_secrets() -> Result<()> {
6290 let p: crate::crypto::Password = "streng geheim".into();
6291 let (mut cert, _) = CertBuilder::new()
6292 .add_transport_encryption_subkey()
6293 .set_password(Some(p.clone()))
6294 .generate()?;
6295 assert_eq!(cert.keys().secret().count(), 2);
6296 assert_eq!(cert.keys().unencrypted_secret().count(), 0);
6297
6298 for (i, ka) in cert.clone().keys().secret().enumerate() {
6299 let key = ka.key().clone().decrypt_secret(&p)?;
6300 cert = if i == 0 {
6301 cert.insert_packets(key.role_into_primary())?.0
6302 } else {
6303 cert.insert_packets(key.role_into_subordinate())?.0
6304 };
6305 assert_eq!(cert.keys().secret().count(), 2);
6306 assert_eq!(cert.keys().unencrypted_secret().count(), i + 1);
6307 }
6308
6309 assert_eq!(cert.keys().secret().count(), 2);
6310 assert_eq!(cert.keys().unencrypted_secret().count(), 2);
6311
6312 for (i, ka) in cert.clone().keys().secret().enumerate() {
6313 let key = ka.key().clone().encrypt_secret(&p)?;
6314 cert = if i == 0 {
6315 cert.insert_packets(key.role_into_primary())?.0
6316 } else {
6317 cert.insert_packets(key.role_into_subordinate())?.0
6318 };
6319 assert_eq!(cert.keys().secret().count(), 2);
6320 assert_eq!(cert.keys().unencrypted_secret().count(), 2 - 1 - i);
6321 }
6322
6323 assert_eq!(cert.keys().secret().count(), 2);
6324 assert_eq!(cert.keys().unencrypted_secret().count(), 0);
6325 Ok(())
6326 }
6327
6328 /// Tests that Cert:.into_packets() and Cert::serialize(..) agree.
6329 #[test]
6330 fn test_into_packets() -> Result<()> {
6331 use crate::serialize::SerializeInto;
6332
6333 let dkg = Cert::from_bytes(crate::tests::key("dkg.pgp"))?;
6334 let mut buf = Vec::new();
6335 for p in dkg.clone().into_packets() {
6336 p.serialize(&mut buf)?;
6337 }
6338 let dkg = dkg.to_vec()?;
6339 #[expect(clippy::overly_complex_bool_expr)]
6340 if false && buf != dkg {
6341 std::fs::write("/tmp/buf", &buf)?;
6342 std::fs::write("/tmp/dkg", &dkg)?;
6343 }
6344 assert_eq!(buf, dkg);
6345 Ok(())
6346 }
6347
6348 #[test]
6349 fn test_canonicalization() -> Result<()> {
6350 let p = crate::policy::StandardPolicy::new();
6351
6352 let primary: Key<_, key::PrimaryRole> =
6353 key::Key6::generate_ecc(true, Curve::Ed25519)?.into();
6354 let cert = Cert::try_from(vec![primary.into()])?;
6355
6356 // We now add components without binding signatures. They
6357 // should be kept, be enumerable, but ignored if a policy is
6358 // applied.
6359
6360 // Add a bare userid.
6361 let uid = UserID::from("foo@example.org");
6362 let cert = cert.insert_packets(uid)?.0;
6363 assert_eq!(cert.userids().count(), 1);
6364 assert_eq!(cert.userids().with_policy(&p, None).count(), 0);
6365
6366 // Add a bare user attribute.
6367 use packet::user_attribute::{Subpacket, Image};
6368 let ua = UserAttribute::new(&[
6369 Subpacket::Image(
6370 Image::Private(100, vec![0, 1, 2].into_boxed_slice())),
6371 ])?;
6372 let cert = cert.insert_packets(ua)?.0;
6373 assert_eq!(cert.user_attributes().count(), 1);
6374 assert_eq!(cert.user_attributes().with_policy(&p, None).count(), 0);
6375
6376 // Add a bare signing subkey.
6377 let signing_subkey: Key<_, key::SubordinateRole> =
6378 key::Key6::generate_ecc(true, Curve::Ed25519)?.into();
6379 let _signing_subkey_pair = signing_subkey.clone().into_keypair()?;
6380 let cert = cert.insert_packets(signing_subkey)?.0;
6381 assert_eq!(cert.keys().subkeys().count(), 1);
6382 assert_eq!(cert.keys().subkeys().with_policy(&p, None).count(), 0);
6383
6384 // Add a component that Sequoia doesn't understand.
6385 let mut fake_key = packet::Unknown::new(
6386 packet::Tag::PublicSubkey, anyhow::anyhow!("fake key"));
6387 fake_key.set_body("fake key".into());
6388 let cert = cert.insert_packets(vec![Packet::from(fake_key)])?.0;
6389 assert_eq!(cert.unknowns().count(), 1);
6390 assert_eq!(cert.unknowns().next().unwrap().unknown().tag(),
6391 packet::Tag::PublicSubkey);
6392
6393 Ok(())
6394 }
6395
6396 #[test]
6397 #[allow(deprecated)]
6398 fn canonicalize_with_v3_sig() -> Result<()> {
6399 skip_unless_supported!(crate::types::PublicKeyAlgorithm::DSA);
6400
6401 // This test relies on being able to validate SHA-1
6402 // signatures. The standard policy rejects SHA-1. So, use a
6403 // custom policy.
6404 let p = &P::new();
6405 let sha1 =
6406 p.hash_cutoff(
6407 HashAlgorithm::SHA1, HashAlgoSecurity::CollisionResistance)
6408 .unwrap();
6409 let p = &P::at(sha1 - std::time::Duration::from_secs(1));
6410
6411 let cert = Cert::from_bytes(
6412 crate::tests::key("eike-v3-v4.pgp"))?;
6413 dbg!(&cert);
6414 assert_eq!(cert.userids()
6415 .with_policy(p, None)
6416 .count(), 1);
6417 Ok(())
6418 }
6419
6420 /// Asserts that key expiration times on direct key signatures are
6421 /// honored.
6422 #[test]
6423 fn issue_215() {
6424 let p = &P::new();
6425 let cert = Cert::from_bytes(crate::tests::key(
6426 "issue-215-expiration-on-direct-key-sig.pgp")).unwrap();
6427 assert_match!(
6428 Error::Expired(_)
6429 = cert.with_policy(p, None).unwrap().alive()
6430 .unwrap_err().downcast().unwrap());
6431 assert_match!(
6432 Error::Expired(_)
6433 = cert.primary_key().with_policy(p, None).unwrap()
6434 .alive().unwrap_err().downcast().unwrap());
6435 }
6436
6437 /// Tests that secrets are kept when merging.
6438 #[test]
6439 fn merge_keeps_secrets() -> Result<()> {
6440 let (cert_s, _) =
6441 CertBuilder::general_purpose(Some("uid")).generate()?;
6442 let cert_p = cert_s.clone().strip_secret_key_material();
6443
6444 // Merge key into cert.
6445 let cert = cert_p.clone().merge_public_and_secret(cert_s.clone())?;
6446 assert!(cert.keys().all(|ka| ka.has_secret()));
6447
6448 // Merge cert into key.
6449 let cert = cert_s.clone().merge_public_and_secret(cert_p.clone())?;
6450 assert!(cert.keys().all(|ka| ka.has_secret()));
6451
6452 Ok(())
6453 }
6454
6455 /// Tests that secrets that are merged in are preferred to
6456 /// existing secrets.
6457 #[test]
6458 fn merge_prefers_merged_in_secrets() -> Result<()> {
6459 let pw: crate::crypto::Password = "foo".into();
6460 let (cert_encrypted_secrets, _) =
6461 CertBuilder::general_purpose(Some("uid"))
6462 .set_password(Some(pw.clone()))
6463 .generate()?;
6464
6465 let mut cert_plain_secrets = cert_encrypted_secrets.clone();
6466 for ka in cert_encrypted_secrets.keys().secret() {
6467 assert!(! ka.key().has_unencrypted_secret());
6468 let key = ka.key().clone().decrypt_secret(&pw)?;
6469 assert!(key.has_unencrypted_secret());
6470
6471 let key: Packet = if ka.primary() {
6472 key.role_into_primary().into()
6473 } else {
6474 key.role_into_subordinate().into()
6475 };
6476
6477 cert_plain_secrets =
6478 cert_plain_secrets.insert_packets(vec![key])?.0;
6479 }
6480 assert!(
6481 cert_plain_secrets.keys().all(|ka| ka.key().has_unencrypted_secret()));
6482
6483 // Merge unencrypted secrets into encrypted secrets.
6484 let cert = cert_encrypted_secrets.clone().merge_public_and_secret(
6485 cert_plain_secrets.clone())?;
6486 assert!(cert.keys().all(|ka| ka.key().has_unencrypted_secret()));
6487
6488 // Merge encrypted secrets into unencrypted secrets.
6489 let cert = cert_plain_secrets.clone().merge_public_and_secret(
6490 cert_encrypted_secrets.clone())?;
6491 assert!(cert.keys().all(|ka| ka.has_secret()
6492 && ! ka.key().has_unencrypted_secret()));
6493
6494 Ok(())
6495 }
6496
6497 /// Tests that secrets are kept when canonicalizing.
6498 #[test]
6499 fn canonicalizing_keeps_secrets() -> Result<()> {
6500 let primary: Key<_, key::PrimaryRole> =
6501 key::Key6::generate_ecc(true, Curve::Ed25519)?.into();
6502 let mut primary_pair = primary.clone().into_keypair()?;
6503 let cert = Cert::try_from(vec![primary.clone().into()])?;
6504
6505 let subkey_sec: Key<_, key::SubordinateRole> =
6506 key::Key6::generate_ecc(false, Curve::Cv25519)?.into();
6507 let subkey_pub = subkey_sec.clone().take_secret().0;
6508 let builder = signature::SignatureBuilder::new(SignatureType::SubkeyBinding)
6509 .set_key_flags(KeyFlags::empty()
6510 .set_transport_encryption())?;
6511 let binding = subkey_sec.bind(&mut primary_pair, &cert, builder)?;
6512
6513 let cert = Cert::try_from(vec![
6514 primary.clone().into(),
6515 subkey_pub.clone().into(),
6516 binding.clone().into(),
6517 subkey_sec.clone().into(),
6518 binding.clone().into(),
6519 ])?;
6520 assert_eq!(cert.keys().subkeys().count(), 1);
6521 assert_eq!(cert.keys().unencrypted_secret().subkeys().count(), 1);
6522
6523 let cert = Cert::try_from(vec![
6524 primary.clone().into(),
6525 subkey_sec.clone().into(),
6526 binding.clone().into(),
6527 subkey_pub.clone().into(),
6528 binding.clone().into(),
6529 ])?;
6530 assert_eq!(cert.keys().subkeys().count(), 1);
6531 assert_eq!(cert.keys().unencrypted_secret().subkeys().count(), 1);
6532 Ok(())
6533 }
6534
6535 /// Demonstrates that subkeys are kept if a userid is later added
6536 /// without any keyflags.
6537 #[test]
6538 fn issue_361() -> Result<()> {
6539 let (cert, _) = CertBuilder::new()
6540 .add_transport_encryption_subkey()
6541 .generate()?;
6542 let p = &P::new();
6543 let cert_at = cert.with_policy(p,
6544 cert.primary_key().key().creation_time()
6545 + time::Duration::new(300, 0))
6546 .unwrap();
6547 assert_eq!(cert_at.userids().count(), 0);
6548 assert_eq!(cert_at.keys().count(), 2);
6549
6550 let mut primary_pair = cert.primary_key().key().clone()
6551 .parts_into_secret()?.into_keypair()?;
6552 let uid: UserID = "foo@example.org".into();
6553 let sig = uid.bind(
6554 &mut primary_pair, &cert,
6555 signature::SignatureBuilder::new(SignatureType::PositiveCertification))?;
6556 let cert = cert.insert_packets(vec![
6557 Packet::from(uid),
6558 sig.into(),
6559 ])?.0;
6560
6561 let cert_at = cert.with_policy(p,
6562 cert.primary_key().key().creation_time()
6563 + time::Duration::new(300, 0))
6564 .unwrap();
6565 assert_eq!(cert_at.userids().count(), 1);
6566 assert_eq!(cert_at.keys().count(), 2);
6567 Ok(())
6568 }
6569
6570 /// Demonstrates that binding signatures are considered valid even
6571 /// if the primary key is not marked as certification-capable.
6572 #[test]
6573 fn issue_321() -> Result<()> {
6574 let cert = Cert::from_bytes(
6575 crate::tests::file("contrib/pep/pEpkey-netpgp.asc"))?;
6576 assert_eq!(cert.userids().count(), 1);
6577 assert_eq!(cert.keys().count(), 1);
6578
6579 let mut p = P::new();
6580 p.accept_hash(HashAlgorithm::SHA1);
6581 let cert_at = cert.with_policy(&p, cert.primary_key().key().creation_time())
6582 .unwrap();
6583 assert_eq!(cert_at.userids().count(), 1);
6584 assert_eq!(cert_at.keys().count(), 1);
6585 Ok(())
6586 }
6587
6588 #[test]
6589 fn policy_uri_some() -> Result<()> {
6590 use crate::packet::prelude::SignatureBuilder;
6591 use crate::policy::StandardPolicy;
6592
6593 let p = &StandardPolicy::new();
6594
6595 let (alice, _) = CertBuilder::new().add_userid("Alice").generate()?;
6596
6597 let sig = SignatureBuilder::from(
6598 alice
6599 .with_policy(p, None)?
6600 .direct_key_signature().expect("Direct key signature")
6601 .clone()
6602 )
6603 .set_policy_uri("https://example.org/~alice/signing-policy.txt")?;
6604 assert_eq!(sig.policy_uri(), Some("https://example.org/~alice/signing-policy.txt".as_bytes()));
6605 Ok(())
6606 }
6607
6608 #[test]
6609 fn policy_uri_none() -> Result<()> {
6610 use crate::packet::prelude::SignatureBuilder;
6611 use crate::policy::StandardPolicy;
6612
6613 let p = &StandardPolicy::new();
6614
6615 let (alice, _) = CertBuilder::new().add_userid("Alice").generate()?;
6616
6617 let sig = SignatureBuilder::from(
6618 alice
6619 .with_policy(p, None)?
6620 .direct_key_signature().expect("Direct key signature")
6621 .clone()
6622 );
6623 assert_eq!(sig.policy_uri(), None);
6624 Ok(())
6625 }
6626
6627 #[test]
6628 #[allow(deprecated)]
6629 fn different_preferences() -> Result<()> {
6630 use crate::cert::Preferences;
6631 let p = &crate::policy::StandardPolicy::new();
6632
6633 // This key returns different preferences depending on how you
6634 // address it. (It has two user ids and the user ids have
6635 // different preference packets on their respective self
6636 // signatures.)
6637
6638 let cert = Cert::from_bytes(
6639 crate::tests::key("different-preferences.asc"))?;
6640 assert_eq!(cert.userids().count(), 2);
6641
6642 if let Some(userid) = cert.userids().next() {
6643 assert_eq!(userid.userid().value(),
6644 &b"Alice Confusion <alice@example.com>"[..]);
6645
6646 let userid = userid.with_policy(p, None).expect("valid");
6647
6648 use crate::types::SymmetricAlgorithm::*;
6649 assert_eq!(userid.preferred_symmetric_algorithms(),
6650 Some(&[ AES256, AES192, AES128, TripleDES ][..]));
6651
6652 use crate::types::HashAlgorithm::*;
6653 assert_eq!(userid.preferred_hash_algorithms(),
6654 Some(&[ SHA512, SHA384, SHA256, SHA224, SHA1 ][..]));
6655
6656 use crate::types::CompressionAlgorithm::*;
6657 assert_eq!(userid.preferred_compression_algorithms(),
6658 Some(&[ Zlib, BZip2, Zip ][..]));
6659
6660 assert_eq!(userid.preferred_aead_ciphersuites(), None);
6661
6662 // assert_eq!(userid.key_server_preferences(),
6663 // Some(KeyServerPreferences::new(&[])));
6664
6665 assert_eq!(userid.features(),
6666 Some(Features::new(&[]).set_seipdv1()));
6667 } else {
6668 panic!("two user ids");
6669 }
6670
6671 if let Some(userid) = cert.userids().next() {
6672 assert_eq!(userid.userid().value(),
6673 &b"Alice Confusion <alice@example.com>"[..]);
6674
6675 let userid = userid.with_policy(p, None).expect("valid");
6676
6677 use crate::types::SymmetricAlgorithm::*;
6678 assert_eq!(userid.preferred_symmetric_algorithms(),
6679 Some(&[ AES256, AES192, AES128, TripleDES ][..]));
6680
6681 use crate::types::HashAlgorithm::*;
6682 assert_eq!(userid.preferred_hash_algorithms(),
6683 Some(&[ SHA512, SHA384, SHA256, SHA224, SHA1 ][..]));
6684
6685 use crate::types::CompressionAlgorithm::*;
6686 assert_eq!(userid.preferred_compression_algorithms(),
6687 Some(&[ Zlib, BZip2, Zip ][..]));
6688
6689 assert_eq!(userid.preferred_aead_ciphersuites(), None);
6690
6691 assert_eq!(userid.key_server_preferences(),
6692 Some(KeyServerPreferences::new(&[0x80])));
6693
6694 assert_eq!(userid.features(),
6695 Some(Features::new(&[]).set_seipdv1()));
6696
6697 // Using the certificate should choose the primary user
6698 // id, which is this one (because it is lexicographically
6699 // earlier).
6700 let cert = cert.with_policy(p, None).expect("valid");
6701 assert_eq!(userid.preferred_symmetric_algorithms(),
6702 cert.preferred_symmetric_algorithms());
6703 assert_eq!(userid.preferred_hash_algorithms(),
6704 cert.preferred_hash_algorithms());
6705 assert_eq!(userid.preferred_compression_algorithms(),
6706 cert.preferred_compression_algorithms());
6707 assert_eq!(userid.preferred_aead_ciphersuites(),
6708 cert.preferred_aead_ciphersuites());
6709 assert_eq!(userid.key_server_preferences(),
6710 cert.key_server_preferences());
6711 assert_eq!(userid.features(),
6712 cert.features());
6713 } else {
6714 panic!("two user ids");
6715 }
6716
6717 if let Some(userid) = cert.userids().nth(1) {
6718 assert_eq!(userid.userid().value(),
6719 &b"Alice Confusion <alice@example.net>"[..]);
6720
6721 let userid = userid.with_policy(p, None).expect("valid");
6722
6723 use crate::types::SymmetricAlgorithm::*;
6724 assert_eq!(userid.preferred_symmetric_algorithms(),
6725 Some(&[ AES192, AES256, AES128, TripleDES ][..]));
6726
6727 use crate::types::HashAlgorithm::*;
6728 assert_eq!(userid.preferred_hash_algorithms(),
6729 Some(&[ SHA384, SHA512, SHA256, SHA224, SHA1 ][..]));
6730
6731 use crate::types::CompressionAlgorithm::*;
6732 assert_eq!(userid.preferred_compression_algorithms(),
6733 Some(&[ BZip2, Zlib, Zip ][..]));
6734
6735 assert_eq!(userid.preferred_aead_ciphersuites(), None);
6736
6737 assert_eq!(userid.key_server_preferences(),
6738 Some(KeyServerPreferences::new(&[0x80])));
6739
6740 assert_eq!(userid.features(),
6741 Some(Features::new(&[]).set_seipdv1()));
6742 } else {
6743 panic!("two user ids");
6744 }
6745
6746 Ok(())
6747 }
6748
6749 #[test]
6750 fn unsigned_components() -> Result<()> {
6751 // We have a certificate with an unsigned User ID, User
6752 // Attribute, encryption-capable subkey, and signing-capable
6753 // subkey. (Actually, they are signed, but the signatures are
6754 // bad.) We expect that when we parse such a certificate the
6755 // unsigned components are not dropped and they appear when
6756 // iterating over the components using, e.g., Cert::userids,
6757 // but not when we check for valid components.
6758
6759 let p = &crate::policy::StandardPolicy::new();
6760
6761 let cert = Cert::from_bytes(
6762 crate::tests::key("certificate-with-unsigned-components.asc"))?;
6763
6764 assert_eq!(cert.userids().count(), 2);
6765 assert_eq!(cert.userids().with_policy(p, None).count(), 1);
6766
6767 assert_eq!(cert.user_attributes().count(), 2);
6768 assert_eq!(cert.user_attributes().with_policy(p, None).count(), 1);
6769
6770 assert_eq!(cert.keys().count(), 1 + 4);
6771 assert_eq!(cert.keys().with_policy(p, None).count(), 1 + 2);
6772 Ok(())
6773 }
6774
6775 #[test]
6776 fn issue_504() -> Result<()> {
6777 let mut keyring = crate::tests::key("testy.pgp").to_vec();
6778 keyring.extend_from_slice(crate::tests::key("testy-new.pgp"));
6779
6780 // TryFrom<PacketPile>
6781 let pp = PacketPile::from_bytes(&keyring)?;
6782 assert!(matches!(
6783 Cert::try_from(pp.clone()).unwrap_err().downcast().unwrap(),
6784 Error::MalformedCert(_)
6785 ));
6786
6787 // Cert::TryFrom<Vec<Packet>>
6788 let v: Vec<Packet> = pp.into();
6789 assert!(matches!(
6790 Cert::try_from(v.clone()).unwrap_err().downcast().unwrap(),
6791 Error::MalformedCert(_)
6792 ));
6793
6794 // Cert::from_packet
6795 assert!(matches!(
6796 Cert::from_packets(v.into_iter()).unwrap_err().downcast().unwrap(),
6797 Error::MalformedCert(_)
6798 ));
6799
6800 // Cert::TryFrom<PacketParserResult>
6801 let ppr = PacketParser::from_bytes(&keyring)?;
6802 assert!(matches!(
6803 Cert::try_from(ppr).unwrap_err().downcast().unwrap(),
6804 Error::MalformedCert(_)
6805 ));
6806 Ok(())
6807 }
6808
6809 /// Tests whether the policy is applied to primary key binding
6810 /// signatures.
6811 #[test]
6812 fn issue_531() -> Result<()> {
6813 let cert =
6814 Cert::from_bytes(crate::tests::key("peter-sha1-backsig.pgp"))?;
6815 let p = unsafe { &crate::policy::NullPolicy::new() };
6816 assert_eq!(cert.with_policy(p, None)?.keys().for_signing().count(), 1);
6817 let mut p = crate::policy::StandardPolicy::new();
6818 p.reject_hash(HashAlgorithm::SHA1);
6819 assert_eq!(cert.with_policy(&p, None)?.keys().for_signing().count(), 0);
6820 Ok(())
6821 }
6822
6823 /// Tests whether expired primary key binding signatures are
6824 /// rejected.
6825 #[test]
6826 fn issue_539() -> Result<()> {
6827 let cert =
6828 Cert::from_bytes(crate::tests::key("peter-expired-backsig.pgp"))?;
6829 let p = unsafe { &crate::policy::NullPolicy::new() };
6830 assert_eq!(cert.with_policy(p, None)?.keys().for_signing().count(), 0);
6831 let p = &crate::policy::StandardPolicy::new();
6832 assert_eq!(cert.with_policy(p, None)?.keys().for_signing().count(), 0);
6833 Ok(())
6834 }
6835
6836 /// Tests whether signatures are properly deduplicated.
6837 #[test]
6838 fn issue_568() -> Result<()> {
6839 use crate::packet::signature::subpacket::*;
6840
6841 let (cert, _) = CertBuilder::general_purpose(
6842 Some("alice@example.org")).generate().unwrap();
6843 assert_eq!(cert.userids().count(), 1);
6844 assert_eq!(cert.subkeys().count(), 2);
6845 assert_eq!(cert.unknowns().count(), 0);
6846 assert_eq!(cert.bad_signatures().count(), 0);
6847 assert_eq!(cert.userids().next().unwrap().self_signatures().count(), 1);
6848 assert_eq!(cert.subkeys().next().unwrap().self_signatures().count(), 1);
6849 assert_eq!(cert.subkeys().nth(1).unwrap().self_signatures().count(), 1);
6850
6851 // Create a variant of cert where the signatures have
6852 // additional information in the unhashed area.
6853 let cert_b = cert.clone();
6854 let mut packets = crate::PacketPile::from(cert_b).into_children()
6855 .collect::<Vec<_>>();
6856 for p in packets.iter_mut() {
6857 if let Packet::Signature(sig) = p {
6858 assert_eq!(sig.hashed_area().subpackets(
6859 SubpacketTag::IssuerFingerprint).count(),
6860 1);
6861 sig.unhashed_area_mut().add(Subpacket::new(
6862 SubpacketValue::Issuer("AAAA BBBB CCCC DDDD".parse()?),
6863 false)?)?;
6864 }
6865 }
6866 let cert_b = Cert::from_packets(packets.into_iter())?;
6867 let cert = cert.merge_public_and_secret(cert_b)?;
6868 assert_eq!(cert.userids().count(), 1);
6869 assert_eq!(cert.subkeys().count(), 2);
6870 assert_eq!(cert.unknowns().count(), 0);
6871 assert_eq!(cert.bad_signatures().count(), 0);
6872 assert_eq!(cert.userids().next().unwrap().self_signatures().count(), 1);
6873 assert_eq!(cert.subkeys().next().unwrap().self_signatures().count(), 1);
6874 assert_eq!(cert.subkeys().nth(1).unwrap().self_signatures().count(), 1);
6875
6876 Ok(())
6877 }
6878
6879 /// Checks that missing or bad embedded signatures cause the
6880 /// signature to be considered bad.
6881 #[test]
6882 fn missing_backsig_is_bad() -> Result<()> {
6883 use crate::packet::{
6884 key::Key6,
6885 signature::{
6886 SignatureBuilder,
6887 subpacket::{Subpacket, SubpacketValue},
6888 },
6889 };
6890
6891 // We'll study this certificate, because it contains a
6892 // signing-capable subkey.
6893 let cert = crate::Cert::from_bytes(crate::tests::key(
6894 "emmelie-dorothea-dina-samantha-awina-ed25519.pgp"))?;
6895 let mut pp = crate::PacketPile::from_bytes(crate::tests::key(
6896 "emmelie-dorothea-dina-samantha-awina-ed25519.pgp"))?;
6897 assert_eq!(pp.children().count(), 5);
6898
6899 if let Some(Packet::Signature(sig)) = pp.path_ref_mut(&[4]) {
6900 // Add a bogus but plausible embedded signature subpacket.
6901 let key: key::SecretKey
6902 = Key6::generate_ecc(true, Curve::Ed25519)?.into();
6903 let mut pair = key.into_keypair()?;
6904
6905 sig.unhashed_area_mut().replace(Subpacket::new(
6906 SubpacketValue::EmbeddedSignature(
6907 SignatureBuilder::new(SignatureType::PrimaryKeyBinding)
6908 .sign_primary_key_binding(
6909 &mut pair,
6910 cert.primary_key().key(),
6911 cert.keys().subkeys().next().unwrap().key())?),
6912 false)?)?;
6913 } else {
6914 panic!("expected a signature");
6915 }
6916
6917 // Parse into cert.
6918 use std::convert::TryFrom;
6919 let malicious_cert = Cert::try_from(pp)?;
6920 // The subkey binding signature should no longer check out.
6921 let p = &crate::policy::StandardPolicy::new();
6922 assert_eq!(malicious_cert.with_policy(p, None)?.keys().subkeys()
6923 .for_signing().count(), 0);
6924 // Instead, it should be considered bad.
6925 assert_eq!(malicious_cert.bad_signatures().count(), 1);
6926 Ok(())
6927 }
6928
6929 /// Checks that multiple embedded signatures are correctly
6930 /// handled.
6931 #[test]
6932 fn multiple_embedded_signatures() -> Result<()> {
6933 use crate::packet::{
6934 key::Key6,
6935 signature::{
6936 SignatureBuilder,
6937 subpacket::{Subpacket, SubpacketValue},
6938 },
6939 };
6940
6941 // We'll study this certificate, because it contains a
6942 // signing-capable subkey.
6943 let cert = crate::Cert::from_bytes(crate::tests::key(
6944 "emmelie-dorothea-dina-samantha-awina-ed25519.pgp"))?;
6945
6946 // Add a bogus but plausible embedded signature subpacket with
6947 // this key.
6948 let key: key::SecretKey
6949 = Key6::generate_ecc(true, Curve::Ed25519)?.into();
6950 let mut pair = key.into_keypair()?;
6951
6952 // Create a malicious cert to merge in.
6953 let mut pp = crate::PacketPile::from_bytes(crate::tests::key(
6954 "emmelie-dorothea-dina-samantha-awina-ed25519.pgp"))?;
6955 assert_eq!(pp.children().count(), 5);
6956
6957 if let Some(Packet::Signature(sig)) = pp.path_ref_mut(&[4]) {
6958 // Prepend a bad backsig.
6959 let backsig = sig.embedded_signatures().next().unwrap().clone();
6960 sig.unhashed_area_mut().replace(Subpacket::new(
6961 SubpacketValue::EmbeddedSignature(
6962 SignatureBuilder::new(SignatureType::PrimaryKeyBinding)
6963 .sign_primary_key_binding(
6964 &mut pair,
6965 cert.primary_key().key(),
6966 cert.keys().subkeys().next().unwrap().key())?),
6967 false)?)?;
6968 sig.unhashed_area_mut().add(Subpacket::new(
6969 SubpacketValue::EmbeddedSignature(backsig), false)?)?;
6970 } else {
6971 panic!("expected a signature");
6972 }
6973
6974 // Parse into cert.
6975 use std::convert::TryFrom;
6976 let malicious_cert = Cert::try_from(pp)?;
6977 // The subkey binding signature should still be fine.
6978 let p = &crate::policy::StandardPolicy::new();
6979 assert_eq!(malicious_cert.with_policy(p, None)?.keys().subkeys()
6980 .for_signing().count(), 1);
6981 assert_eq!(malicious_cert.bad_signatures().count(), 0);
6982
6983 // Now try to merge it in.
6984 let merged = cert.clone().merge_public_and_secret(malicious_cert.clone())?;
6985 // The subkey binding signature should still be fine.
6986 assert_eq!(merged.with_policy(p, None)?.keys().subkeys()
6987 .for_signing().count(), 1);
6988 let sig = merged.with_policy(p, None)?.keys().subkeys()
6989 .for_signing().next().unwrap().binding_signature();
6990 assert_eq!(sig.embedded_signatures().count(), 2);
6991
6992 // Now the other way around.
6993 let merged = malicious_cert.clone().merge_public_and_secret(cert.clone())?;
6994 // The subkey binding signature should still be fine.
6995 assert_eq!(merged.with_policy(p, None)?.keys().subkeys()
6996 .for_signing().count(), 1);
6997 let sig = merged.with_policy(p, None)?.keys().subkeys()
6998 .for_signing().next().unwrap().binding_signature();
6999 assert_eq!(sig.embedded_signatures().count(), 2);
7000 Ok(())
7001 }
7002
7003 /// Checks that Cert::merge(cert, cert) == cert.
7004 #[test]
7005 fn issue_579() -> Result<()> {
7006 use std::convert::TryFrom;
7007 use crate::packet::signature::subpacket::SubpacketTag;
7008
7009 let mut pp = crate::PacketPile::from_bytes(crate::tests::key(
7010 "emmelie-dorothea-dina-samantha-awina-ed25519.pgp"))?;
7011 assert_eq!(pp.children().count(), 5);
7012 // Drop issuer information from the unhashed areas.
7013 if let Some(Packet::Signature(sig)) = pp.path_ref_mut(&[2]) {
7014 sig.unhashed_area_mut().remove_all(SubpacketTag::Issuer);
7015 } else {
7016 panic!("expected a signature");
7017 }
7018 if let Some(Packet::Signature(sig)) = pp.path_ref_mut(&[4]) {
7019 sig.unhashed_area_mut().remove_all(SubpacketTag::Issuer);
7020 } else {
7021 panic!("expected a signature");
7022 }
7023
7024 let cert = Cert::try_from(pp)?;
7025 assert_eq!(cert.clone().merge_public_and_secret(cert.clone())?, cert);
7026
7027 Ok(())
7028 }
7029
7030 /// Checks that Cert::merge_public ignores secret key material.
7031 #[test]
7032 fn merge_public() -> Result<()> {
7033 let cert =
7034 Cert::from_bytes(crate::tests::key("testy-new.pgp"))?;
7035 let key =
7036 Cert::from_bytes(crate::tests::key("testy-new-private.pgp"))?;
7037
7038 assert!(! cert.is_tsk());
7039 assert!(key.is_tsk());
7040
7041 // Secrets are ignored in `other`.
7042 let merged = cert.clone().merge_public(key.clone())?;
7043 assert!(! merged.is_tsk());
7044 assert_eq!(merged, cert);
7045
7046 // Secrets are retained in `self`.
7047 let merged = key.clone().merge_public(cert.clone())?;
7048 assert!(merged.is_tsk());
7049 assert_eq!(merged, key);
7050
7051 Ok(())
7052 }
7053
7054 /// Make sure we can parse a key where the primary key is its own
7055 /// subkeys.
7056 #[test]
7057 fn primary_key_is_subkey() -> Result<()> {
7058 let p = &crate::policy::StandardPolicy::new();
7059
7060 let cert =
7061 Cert::from_bytes(crate::tests::key("primary-key-is-also-subkey.pgp"))?;
7062
7063 // There should be three keys:
7064 //
7065 // Fingerprint: 8E8C 33FA 4626 3379 76D9 7978 069C 0C34 8DD8 2C19
7066 // Public-key algo: EdDSA Edwards-curve Digital Signature Algorithm
7067 // Public-key size: 256 bits
7068 // Secret key: Unencrypted
7069 // Creation time: 2018-06-11 14:12:09 UTC
7070 // Key flags: certification, signing
7071 //
7072 // Subkey: 8E8C 33FA 4626 3379 76D9 7978 069C 0C34 8DD8 2C19
7073 // Public-key algo: EdDSA Edwards-curve Digital Signature Algorithm
7074 // Public-key size: 256 bits
7075 // Secret key: Unencrypted
7076 // Creation time: 2018-06-11 14:12:09 UTC
7077 // Key flags: certification, signing
7078 //
7079 // Subkey: 061C 3CA4 4AFF 0EC5 8DC6 6E95 22E3 FAFE 96B5 6C32
7080 // Public-key algo: EdDSA Edwards-curve Digital Signature Algorithm
7081 // Public-key size: 256 bits
7082 // Secret key: Unencrypted
7083 // Creation time: 2018-08-27 10:55:43 UTC
7084 // Key flags: signing
7085 //
7086 // UserID: Emmelie Dorothea Dina Samantha Awina Ed25519
7087 assert_eq!(cert.keys().count(), 3);
7088
7089 // Make sure there is a subkey with the same fingerprint as
7090 // the primary key.
7091 assert!(cert.keys().subkeys().any(|k| {
7092 k.key().fingerprint() == cert.primary_key().key().fingerprint()
7093 }));
7094
7095 // Make sure the self sig is valid, too.
7096 assert_eq!(cert.keys().count(), 3);
7097
7098 let vc = cert.with_policy(p, None)?;
7099 assert!(vc.keys().subkeys().any(|k| {
7100 k.key().fingerprint() == vc.primary_key().key().fingerprint()
7101 }));
7102
7103 Ok(())
7104 }
7105
7106 /// Makes sure that certification approval key signatures are
7107 /// correctly handled.
7108 #[test]
7109 fn certificaton_approval_signatures() -> Result<()> {
7110 use crate::{
7111 packet::signature::SignatureBuilder,
7112 types::*,
7113 };
7114 let p = &crate::policy::StandardPolicy::new();
7115
7116 let (alice, _) = CertBuilder::new()
7117 .add_userid("alice@foo.com")
7118 .generate()?;
7119 let mut alice_signer =
7120 alice.primary_key().key().clone().parts_into_secret()?
7121 .into_keypair()?;
7122
7123 let (bob, _) = CertBuilder::new()
7124 .add_userid("bob@bar.com")
7125 .generate()?;
7126 let mut bob_signer =
7127 bob.primary_key().key().clone().parts_into_secret()?
7128 .into_keypair()?;
7129 let bob_pristine = bob.clone();
7130
7131 // Have Alice certify the binding between "bob@bar.com" and
7132 // Bob's key.
7133 let alice_certifies_bob
7134 = bob.userids().next().unwrap().userid().bind(
7135 &mut alice_signer, &bob,
7136 SignatureBuilder::new(SignatureType::GenericCertification))?;
7137 let bob = bob.insert_packets(vec![
7138 alice_certifies_bob.clone(),
7139 ])?.0;
7140
7141 assert_eq!(bob.with_policy(p, None)?.userids().next().unwrap()
7142 .certifications().count(), 1);
7143 assert_eq!(bob.with_policy(p, None)?.userids().next().unwrap()
7144 .approved_certifications().count(), 0);
7145
7146 // Have Bob attest that certification.
7147 let attestations =
7148 bob.userids().next().unwrap().approve_of_certifications(
7149 p,
7150 None,
7151 &mut bob_signer,
7152 vec![&alice_certifies_bob])?;
7153 assert_eq!(attestations.len(), 1);
7154 let attestation = attestations[0].clone();
7155
7156 let bob = bob.insert_packets(vec![
7157 attestation.clone(),
7158 ])?.0;
7159
7160 assert_eq!(bob.bad_signatures().count(), 0);
7161 assert_eq!(bob.userids().next().unwrap().certifications().next(),
7162 Some(&alice_certifies_bob));
7163 assert_eq!(bob.userids().next().unwrap().bundle().approvals().next().unwrap(),
7164 &attestation);
7165 assert_eq!(bob.with_policy(p, None)?.userids().next().unwrap()
7166 .certifications().count(), 1);
7167 assert_eq!(bob.with_policy(p, None)?.userids().next().unwrap()
7168 .approved_certifications().count(), 1);
7169
7170 // Check that attested key signatures are kept over merges.
7171 let bob_ = bob.clone().merge_public(bob_pristine.clone())?;
7172 assert_eq!(bob_.bad_signatures().count(), 0);
7173 assert_eq!(bob_.userids().next().unwrap().certifications().next(),
7174 Some(&alice_certifies_bob));
7175 assert_eq!(bob_.userids().next().unwrap().bundle().approvals().next().unwrap(),
7176 &attestation);
7177 assert_eq!(bob_.with_policy(p, None)?.userids().next().unwrap()
7178 .approved_certifications().count(), 1);
7179
7180 // And the other way around.
7181 let bob_ = bob_pristine.clone().merge_public(bob.clone())?;
7182 assert_eq!(bob_.bad_signatures().count(), 0);
7183 assert_eq!(bob_.userids().next().unwrap().certifications().next(),
7184 Some(&alice_certifies_bob));
7185 assert_eq!(bob_.userids().next().unwrap().bundle().approvals().next().unwrap(),
7186 &attestation);
7187 assert_eq!(bob_.with_policy(p, None)?.userids().next().unwrap()
7188 .approved_certifications().count(), 1);
7189
7190 // Have Bob withdraw any prior attestations.
7191
7192 let attestations =
7193 bob.userids().next().unwrap().approve_of_certifications(
7194 p,
7195 None,
7196 &mut bob_signer,
7197 &[])?;
7198 assert_eq!(attestations.len(), 1);
7199 let attestation = attestations[0].clone();
7200
7201 let bob = bob.insert_packets(vec![
7202 attestation.clone(),
7203 ])?.0;
7204
7205 assert_eq!(bob.bad_signatures().count(), 0);
7206 assert_eq!(bob.userids().next().unwrap().certifications().next(),
7207 Some(&alice_certifies_bob));
7208 assert_eq!(bob.userids().next().unwrap().bundle().approvals().next().unwrap(),
7209 &attestation);
7210 assert_eq!(bob.with_policy(p, None)?.userids().next().unwrap()
7211 .certifications().count(), 1);
7212 assert_eq!(bob.with_policy(p, None)?.userids().next().unwrap()
7213 .approved_certifications().count(), 0);
7214
7215
7216 Ok(())
7217 }
7218
7219 /// Makes sure that certification approval key signatures are
7220 /// correctly handled.
7221 #[test]
7222 fn certification_approval_key_signatures_dkgpg() -> Result<()> {
7223 const DUMP: bool = false;
7224 let p = &crate::policy::StandardPolicy::new();
7225
7226 let test = Cert::from_bytes(crate::tests::key("1pa3pc-dkgpg.pgp"))?;
7227 assert_eq!(test.bad_signatures().count(), 0);
7228 assert_eq!(test.userids().next().unwrap().certifications().count(),
7229 1);
7230 assert_eq!(test.userids().next().unwrap().bundle().approvals().count(),
7231 1);
7232
7233 let attestation =
7234 test.userids().next().unwrap().bundle().approvals().next().unwrap();
7235
7236 if DUMP {
7237 for (i, d) in attestation.approved_certifications()?.enumerate() {
7238 crate::fmt::hex::Dumper::new(std::io::stderr(), "")
7239 .write(d, format!("expected digest {}", i))?;
7240 }
7241 }
7242
7243 let digests: std::collections::HashSet<_> =
7244 attestation.approved_certifications()?.collect();
7245
7246 for (i, certification) in
7247 test.userids().next().unwrap().certifications().enumerate()
7248 {
7249 // Hash the certification.
7250 let mut h = attestation.hash_algo().context()?
7251 .for_signature(attestation.version());
7252 certification.hash_for_confirmation(&mut h)?;
7253 let digest = h.into_digest()?;
7254
7255 if DUMP {
7256 crate::fmt::hex::Dumper::new(std::io::stderr(), "")
7257 .write(&digest, format!("computed digest {}", i))?;
7258 }
7259
7260 assert!(digests.contains(&digest[..]));
7261 }
7262
7263 assert_eq!(test.with_policy(p, None)?.userids().next().unwrap()
7264 .certifications().count(), 1);
7265 assert_eq!(test.with_policy(p, None)?.userids().next().unwrap()
7266 .approved_certifications().count(), 1);
7267
7268 Ok(())
7269 }
7270
7271 /// Makes sure that certification approval key signatures are
7272 /// correctly reordered.
7273 #[test]
7274 fn certification_approval_key_signature_out_of_order() -> Result<()> {
7275 let p = &crate::policy::StandardPolicy::new();
7276
7277 let (alice, _) = CertBuilder::general_purpose(
7278 Some("alice@example.org")).generate().unwrap();
7279 assert!(alice.keys().subkeys().count() > 0);
7280 let mut alice_signer =
7281 alice.primary_key().key().clone().parts_into_secret()?
7282 .into_keypair()?;
7283
7284 // Now, create new attestation signatures.
7285 let mut attestation_signatures = Vec::new();
7286 for uid in alice.userids() {
7287 attestation_signatures.append(&mut uid.approve_of_certifications(
7288 p,
7289 None,
7290 &mut alice_signer,
7291 uid.certifications(),
7292 )?);
7293 }
7294
7295 // Add the new signatures. This appends the attestation
7296 // signature so that it is considered part of last component,
7297 // a subkey.
7298 let alice2 = alice.insert_packets(attestation_signatures)?.0;
7299
7300 // Now we make sure the attestation signature was correctly reordered.
7301 assert_eq!(alice2.bad_signatures().count(), 0);
7302 let ua = alice2.userids().next().unwrap();
7303 assert_eq!(ua.approvals().count(), 1);
7304
7305 Ok(())
7306 }
7307
7308 /// Makes sure that marker packets are ignored when parsing certs.
7309 #[test]
7310 fn marker_packets() -> Result<()> {
7311 let cert = Cert::from_bytes(crate::tests::key("neal.pgp"))?;
7312 let mut buf = Vec::new();
7313 Packet::Marker(Default::default()).serialize(&mut buf)?;
7314 cert.serialize(&mut buf)?;
7315
7316 let cert_ = Cert::from_bytes(&buf)?;
7317 assert_eq!(cert, cert_);
7318 Ok(())
7319 }
7320
7321 /// Checks that messing with a revocation signature merely
7322 /// invalidates the signature and keeps the cert's revocation
7323 /// status unchanged.
7324 #[test]
7325 fn issue_486() -> Result<()> {
7326 use crate::{
7327 crypto::mpi,
7328 types::RevocationStatus::*,
7329 packet::signature::Signature4,
7330 policy::StandardPolicy,
7331 };
7332 let p = &StandardPolicy::new();
7333
7334 let (cert, revocation) = CertBuilder::new().generate()?;
7335
7336 // Base case.
7337 let c = cert.clone().insert_packets(Some(revocation.clone()))?.0;
7338 if let Revoked(_) = c.revocation_status(p, None) {
7339 // cert is considered revoked
7340 } else {
7341 panic!("Should be revoked, but is not: {:?}",
7342 c.revocation_status(p, None));
7343 }
7344
7345 // Breaking the revocation signature by changing the MPIs.
7346 let c = cert.clone().insert_packets(Some(
7347 Signature4::new(
7348 revocation.typ(),
7349 revocation.pk_algo(),
7350 revocation.hash_algo(),
7351 revocation.hashed_area().clone(),
7352 revocation.unhashed_area().clone(),
7353 *revocation.digest_prefix(),
7354 // MPI is replaced with a dummy one
7355 mpi::Signature::RSA {
7356 s: mpi::MPI::from(vec![1, 2, 3])
7357 })))?.0;
7358 if let NotAsFarAsWeKnow = c.revocation_status(p, None) {
7359 assert_eq!(c.bad_signatures().count(), 1);
7360 } else {
7361 panic!("Should not be revoked, but is: {:?}",
7362 c.revocation_status(p, None));
7363 }
7364
7365 // Breaking the revocation signature by changing the MPIs and
7366 // the digest prefix.
7367 let c = cert.clone().insert_packets(Some(
7368 Signature4::new(
7369 revocation.typ(),
7370 revocation.pk_algo(),
7371 revocation.hash_algo(),
7372 revocation.hashed_area().clone(),
7373 revocation.unhashed_area().clone(),
7374 // Prefix replaced with a dummy one
7375 [0, 1],
7376 // MPI is replaced with a dummy one
7377 mpi::Signature::RSA {
7378 s: mpi::MPI::from(vec![1, 2, 3])
7379 })))?.0;
7380 if let NotAsFarAsWeKnow = c.revocation_status(p, None) {
7381 assert_eq!(c.bad_signatures().count(), 1);
7382 } else {
7383 panic!("Should not be revoked, but is: {:?}",
7384 c.revocation_status(p, None));
7385 }
7386
7387 Ok(())
7388 }
7389
7390 /// Tests v3 binding signatures.
7391 #[test]
7392 #[allow(deprecated)]
7393 fn v3_binding_signature() -> Result<()> {
7394 skip_unless_supported!(crate::types::PublicKeyAlgorithm::DSA);
7395
7396 let c = Cert::from_bytes(
7397 crate::tests::key("pgp5-dsa-elg-v3-subkey-binding.pgp"))?;
7398 assert_eq!(c.bad_signatures().count(), 0);
7399
7400 let np = unsafe { crate::policy::NullPolicy::new() };
7401
7402 // The subkey is interesting because it is bound using a v3
7403 // signature.
7404 let vcert = c.with_policy(&np, None)?;
7405 assert_eq!(vcert.keys().subkeys().count(), 1);
7406
7407 // XXX: Unfortunately, it being a v3 signature, the subkey has
7408 // no keyflags, limiting its usefulness for now.
7409
7410 // The subkey is interesting because it is bound using a v3
7411 // signature.
7412 assert_eq!(c.keys().subkeys().with_policy(&np, None).count(), 1);
7413
7414 Ok(())
7415 }
7416
7417 /// Tests v3 revocation signatures.
7418 #[test]
7419 fn v3_revocation_signature() -> Result<()> {
7420 skip_unless_supported!(crate::types::PublicKeyAlgorithm::ECDSA);
7421 skip_unless_supported!(crate::types::Curve::NistP521);
7422
7423 let c = Cert::from_bytes(
7424 crate::tests::key("v4-revoked-by-v3.pgp"))?;
7425 assert_eq!(c.bad_signatures().count(), 0);
7426
7427 let sp = crate::policy::StandardPolicy::new();
7428 assert!(matches!(c.revocation_status(&sp, None),
7429 RevocationStatus::Revoked(_)));
7430 Ok(())
7431 }
7432
7433 #[test]
7434 fn v6_minimal_cert() -> Result<()> {
7435 let p = &crate::policy::StandardPolicy::new();
7436 let t = None; // XXX
7437 let cert = Cert::from_bytes(
7438 crate::tests::file("crypto-refresh/v6-minimal-cert.key"))?;
7439 assert_eq!(cert.userids().count(), 0);
7440 let vcert = cert.with_policy(p, t)?;
7441 assert_eq!(vcert.keys().count(), 2);
7442 assert_eq!(vcert.keys().encrypted_secret().count(), 0);
7443 assert_eq!(vcert.keys().unencrypted_secret().count(), 0);
7444 assert_eq!(vcert.keys().for_signing().count(), 1);
7445 assert_eq!(vcert.keys().for_transport_encryption().count(), 1);
7446
7447 let cert = Cert::from_bytes(
7448 crate::tests::file("crypto-refresh/v6-minimal-secret.key")).unwrap();
7449 assert_eq!(cert.userids().count(), 0);
7450 let vcert = cert.with_policy(p, t)?;
7451 assert_eq!(vcert.keys().count(), 2);
7452 assert_eq!(vcert.keys().encrypted_secret().count(), 0);
7453 assert_eq!(vcert.keys().unencrypted_secret().count(), 2);
7454 assert_eq!(vcert.keys().for_signing().count(), 1);
7455 assert_eq!(vcert.keys().for_transport_encryption().count(), 1);
7456
7457 // The following key uses Argon2, and it takes 2 GiB to
7458 // efficiently derive the KEK. This isn't viable on 32 bit
7459 // architectures.
7460 let name = if cfg!(target_pointer_width = "16") {
7461 return Ok(()); // No chance we even got here.
7462 } else if cfg!(target_pointer_width = "32") {
7463 // For 32 bit architectures, we have a test vector which
7464 // uses the "SECOND RECOMMENDED" parameter choice for
7465 // memory constrained systems (see Section 4 of RFC 9106).
7466 "v6-minimal-secret-locked-for-constrained-envs.key"
7467 } else {
7468 // 64 bit or weird. Good luck.
7469 "v6-minimal-secret-locked.key"
7470 };
7471
7472 let cert = Cert::from_bytes(
7473 crate::tests::file(&format!("crypto-refresh/{}", name)))?;
7474 assert_eq!(cert.userids().count(), 0);
7475 let vcert = cert.with_policy(p, t)?;
7476 assert_eq!(vcert.keys().count(), 2);
7477 assert_eq!(vcert.keys().encrypted_secret().count(), 2);
7478 assert_eq!(vcert.keys().unencrypted_secret().count(), 0);
7479 assert_eq!(vcert.keys().for_signing().count(), 1);
7480 assert_eq!(vcert.keys().for_transport_encryption().count(), 1);
7481
7482 let password = "correct horse battery staple".into();
7483 for skb in vcert.keys().encrypted_secret() {
7484 skb.key().secret().clone().decrypt(skb.key(), &password)?;
7485 }
7486
7487 Ok(())
7488 }
7489
7490 // Check that the certificate is valid, and has a primary key and
7491 // an encryption capable subkey. Check that same for the key
7492 // variant, but also assert that the keys have unencrypted secret
7493 // key material.
7494 fn test_parse_certificate(algo: PublicKeyAlgorithm,
7495 cert_file: &str, key_file: &str)
7496 -> Result<()>
7497 {
7498 skip_unless_supported!(algo);
7499
7500 eprintln!("Test {}\n- {}\n- {}", algo, cert_file, key_file);
7501
7502 let p = &crate::policy::StandardPolicy::new();
7503 let t = None;
7504 let cert = Cert::from_bytes(
7505 crate::tests::file(cert_file))?;
7506 assert_eq!(cert.userids().count(), 1);
7507 let vcert = cert.with_policy(p, t)?;
7508 assert_eq!(vcert.keys().count(), 2);
7509 assert_eq!(vcert.keys().encrypted_secret().count(), 0);
7510 assert_eq!(vcert.keys().unencrypted_secret().count(), 0);
7511 assert_eq!(vcert.keys().for_signing().count(), 1);
7512 assert_eq!(vcert.keys().for_transport_encryption().count(), 1);
7513
7514 let cert = Cert::from_bytes(
7515 crate::tests::file(key_file))?;
7516 assert_eq!(cert.userids().count(), 1);
7517 let vcert = cert.with_policy(p, t)?;
7518 assert_eq!(vcert.keys().count(), 2);
7519 assert_eq!(vcert.keys().encrypted_secret().count(), 0);
7520 assert_eq!(vcert.keys().unencrypted_secret().count(), 2);
7521 assert_eq!(vcert.keys().for_signing().count(), 1);
7522 assert_eq!(vcert.keys().for_transport_encryption().count(), 1);
7523
7524 Ok(())
7525 }
7526
7527 // Check that we can parse the certificates and that they have the
7528 // expected form.
7529 #[test]
7530 fn parse_certificates() -> Result<()> {
7531 use crate::tests::PQC_CERT_PAIRS;
7532
7533 for (algo, cert_file, key_file) in PQC_CERT_PAIRS {
7534 assert!(test_parse_certificate(*algo, cert_file, key_file).is_ok());
7535 }
7536
7537 Ok(())
7538 }
7539}