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::serialize::Serialize;
4386 use crate::policy::StandardPolicy as P;
4387 use crate::types::Curve;
4388 use crate::packet::signature;
4389 use crate::policy::HashAlgoSecurity;
4390 use super::*;
4391
4392 use crate::{
4393 KeyID,
4394 types::KeyFlags,
4395 };
4396
4397 fn parse_cert(data: &[u8], as_message: bool) -> Result<Cert> {
4398 if as_message {
4399 let pile = PacketPile::from_bytes(data).unwrap();
4400 Cert::try_from(pile)
4401 } else {
4402 Cert::from_bytes(data)
4403 }
4404 }
4405
4406 #[test]
4407 fn broken() {
4408 use crate::types::Timestamp;
4409 for i in 0..2 {
4410 let cert = parse_cert(crate::tests::key("testy-broken-no-pk.pgp"),
4411 i == 0);
4412 assert_match!(Error::MalformedCert(_)
4413 = cert.err().unwrap().downcast::<Error>().unwrap());
4414
4415 // According to 4880, a Cert must have a UserID. But, we
4416 // don't require it.
4417 let cert = parse_cert(crate::tests::key("testy-broken-no-uid.pgp"),
4418 i == 0);
4419 assert!(cert.is_ok());
4420
4421 // We have:
4422 //
4423 // [ pk, user id, sig, subkey ]
4424 let cert = parse_cert(crate::tests::key("testy-broken-no-sig-on-subkey.pgp"),
4425 i == 0).unwrap();
4426 assert_eq!(cert.primary.key().creation_time(),
4427 Timestamp::from(1511355130).into());
4428 assert_eq!(cert.userids.len(), 1);
4429 assert_eq!(cert.userids[0].userid().value(),
4430 &b"Testy McTestface <testy@example.org>"[..]);
4431 assert_eq!(cert.userids[0].self_signatures().count(), 1);
4432 assert_eq!(cert.userids[0].self_signatures().next().unwrap()
4433 .digest_prefix(),
4434 &[ 0xc6, 0x8f ]);
4435 assert_eq!(cert.user_attributes.len(), 0);
4436 assert_eq!(cert.subkeys.len(), 1);
4437 }
4438 }
4439
4440 #[test]
4441 fn basics() {
4442 use crate::types::Timestamp;
4443 for i in 0..2 {
4444 let cert = parse_cert(crate::tests::key("testy.pgp"),
4445 i == 0).unwrap();
4446 assert_eq!(cert.primary.key().creation_time(),
4447 Timestamp::from(1511355130).into());
4448 assert_eq!(format!("{:X}", cert.fingerprint()),
4449 "3E8877C877274692975189F5D03F6F865226FE8B");
4450
4451 assert_eq!(cert.userids.len(), 1, "number of userids");
4452 assert_eq!(cert.userids[0].userid().value(),
4453 &b"Testy McTestface <testy@example.org>"[..]);
4454 assert_eq!(cert.userids[0].self_signatures().count(), 1);
4455 assert_eq!(cert.userids[0].self_signatures().next().unwrap()
4456 .digest_prefix(),
4457 &[ 0xc6, 0x8f ]);
4458
4459 assert_eq!(cert.user_attributes.len(), 0);
4460
4461 assert_eq!(cert.subkeys.len(), 1, "number of subkeys");
4462 assert_eq!(cert.subkeys[0].key().creation_time(),
4463 Timestamp::from(1511355130).into());
4464 assert_eq!(cert.subkeys[0].self_signatures().next().unwrap()
4465 .digest_prefix(),
4466 &[ 0xb7, 0xb9 ]);
4467
4468 let cert = parse_cert(crate::tests::key("testy-no-subkey.pgp"),
4469 i == 0).unwrap();
4470 assert_eq!(cert.primary.key().creation_time(),
4471 Timestamp::from(1511355130).into());
4472 assert_eq!(format!("{:X}", cert.fingerprint()),
4473 "3E8877C877274692975189F5D03F6F865226FE8B");
4474
4475 assert_eq!(cert.user_attributes.len(), 0);
4476
4477 assert_eq!(cert.userids.len(), 1, "number of userids");
4478 assert_eq!(cert.userids[0].userid().value(),
4479 &b"Testy McTestface <testy@example.org>"[..]);
4480 assert_eq!(cert.userids[0].self_signatures().count(), 1);
4481 assert_eq!(cert.userids[0].self_signatures().next().unwrap()
4482 .digest_prefix(),
4483 &[ 0xc6, 0x8f ]);
4484
4485 assert_eq!(cert.subkeys.len(), 0, "number of subkeys");
4486
4487 let cert = parse_cert(crate::tests::key("testy.asc"), i == 0).unwrap();
4488 assert_eq!(format!("{:X}", cert.fingerprint()),
4489 "3E8877C877274692975189F5D03F6F865226FE8B");
4490 }
4491 }
4492
4493 #[test]
4494 fn only_a_public_key() {
4495 // Make sure the Cert parser can parse a key that just consists
4496 // of a public key---no signatures, no user ids, nothing.
4497 let cert = Cert::from_bytes(crate::tests::key("testy-only-a-pk.pgp")).unwrap();
4498 assert_eq!(cert.userids.len(), 0);
4499 assert_eq!(cert.user_attributes.len(), 0);
4500 assert_eq!(cert.subkeys.len(), 0);
4501 }
4502
4503 #[test]
4504 fn merge() {
4505 use crate::tests::key;
4506 let cert_base = Cert::from_bytes(key("bannon-base.pgp")).unwrap();
4507
4508 // When we merge it with itself, we should get the exact same
4509 // thing.
4510 let merged = cert_base.clone().merge_public_and_secret(cert_base.clone()).unwrap();
4511 assert_eq!(cert_base, merged);
4512
4513 let cert_add_uid_1
4514 = Cert::from_bytes(key("bannon-add-uid-1-whitehouse.gov.pgp"))
4515 .unwrap();
4516 let cert_add_uid_2
4517 = Cert::from_bytes(key("bannon-add-uid-2-fox.com.pgp"))
4518 .unwrap();
4519 // Duplicate user id, but with a different self-sig.
4520 let cert_add_uid_3
4521 = Cert::from_bytes(key("bannon-add-uid-3-whitehouse.gov-dup.pgp"))
4522 .unwrap();
4523
4524 let cert_all_uids
4525 = Cert::from_bytes(key("bannon-all-uids.pgp"))
4526 .unwrap();
4527 // We have four User ID packets, but one has the same User ID,
4528 // just with a different self-signature.
4529 assert_eq!(cert_all_uids.userids.len(), 3);
4530
4531 // Merge in order.
4532 let merged = cert_base.clone().merge_public_and_secret(cert_add_uid_1.clone()).unwrap()
4533 .merge_public_and_secret(cert_add_uid_2.clone()).unwrap()
4534 .merge_public_and_secret(cert_add_uid_3.clone()).unwrap();
4535 assert_eq!(cert_all_uids, merged);
4536
4537 // Merge in reverse order.
4538 let merged = cert_base.clone()
4539 .merge_public_and_secret(cert_add_uid_3.clone()).unwrap()
4540 .merge_public_and_secret(cert_add_uid_2.clone()).unwrap()
4541 .merge_public_and_secret(cert_add_uid_1.clone()).unwrap();
4542 assert_eq!(cert_all_uids, merged);
4543
4544 let cert_add_subkey_1
4545 = Cert::from_bytes(key("bannon-add-subkey-1.pgp")).unwrap();
4546 let cert_add_subkey_2
4547 = Cert::from_bytes(key("bannon-add-subkey-2.pgp")).unwrap();
4548 let cert_add_subkey_3
4549 = Cert::from_bytes(key("bannon-add-subkey-3.pgp")).unwrap();
4550
4551 let cert_all_subkeys
4552 = Cert::from_bytes(key("bannon-all-subkeys.pgp")).unwrap();
4553
4554 // Merge the first user, then the second, then the third.
4555 let merged = cert_base.clone().merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4556 .merge_public_and_secret(cert_add_subkey_2.clone()).unwrap()
4557 .merge_public_and_secret(cert_add_subkey_3.clone()).unwrap();
4558 assert_eq!(cert_all_subkeys, merged);
4559
4560 // Merge the third user, then the second, then the first.
4561 let merged = cert_base.clone().merge_public_and_secret(cert_add_subkey_3.clone()).unwrap()
4562 .merge_public_and_secret(cert_add_subkey_2.clone()).unwrap()
4563 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap();
4564 assert_eq!(cert_all_subkeys, merged);
4565
4566 // Merge a lot.
4567 let merged = cert_base.clone()
4568 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4569 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4570 .merge_public_and_secret(cert_add_subkey_3.clone()).unwrap()
4571 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4572 .merge_public_and_secret(cert_add_subkey_2.clone()).unwrap()
4573 .merge_public_and_secret(cert_add_subkey_3.clone()).unwrap()
4574 .merge_public_and_secret(cert_add_subkey_3.clone()).unwrap()
4575 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4576 .merge_public_and_secret(cert_add_subkey_2.clone()).unwrap();
4577 assert_eq!(cert_all_subkeys, merged);
4578
4579 let cert_all
4580 = Cert::from_bytes(key("bannon-all-uids-subkeys.pgp"))
4581 .unwrap();
4582
4583 // Merge all the subkeys with all the uids.
4584 let merged = cert_all_subkeys.clone()
4585 .merge_public_and_secret(cert_all_uids.clone()).unwrap();
4586 assert_eq!(cert_all, merged);
4587
4588 // Merge all uids with all the subkeys.
4589 let merged = cert_all_uids.clone()
4590 .merge_public_and_secret(cert_all_subkeys.clone()).unwrap();
4591 assert_eq!(cert_all, merged);
4592
4593 // All the subkeys and the uids in a mixed up order.
4594 let merged = cert_base.clone()
4595 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4596 .merge_public_and_secret(cert_add_uid_2.clone()).unwrap()
4597 .merge_public_and_secret(cert_add_uid_1.clone()).unwrap()
4598 .merge_public_and_secret(cert_add_subkey_3.clone()).unwrap()
4599 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4600 .merge_public_and_secret(cert_add_uid_3.clone()).unwrap()
4601 .merge_public_and_secret(cert_add_subkey_2.clone()).unwrap()
4602 .merge_public_and_secret(cert_add_subkey_1.clone()).unwrap()
4603 .merge_public_and_secret(cert_add_uid_2.clone()).unwrap();
4604 assert_eq!(cert_all, merged);
4605
4606 // Certifications.
4607 let cert_donald_signs_base
4608 = Cert::from_bytes(key("bannon-the-donald-signs-base.pgp"))
4609 .unwrap();
4610 let cert_donald_signs_all
4611 = Cert::from_bytes(key("bannon-the-donald-signs-all-uids.pgp"))
4612 .unwrap();
4613 let cert_ivanka_signs_base
4614 = Cert::from_bytes(key("bannon-ivanka-signs-base.pgp"))
4615 .unwrap();
4616 let cert_ivanka_signs_all
4617 = Cert::from_bytes(key("bannon-ivanka-signs-all-uids.pgp"))
4618 .unwrap();
4619
4620 assert!(cert_donald_signs_base.userids.len() == 1);
4621 assert!(cert_donald_signs_base.userids[0].self_signatures().count() == 1);
4622 assert!(cert_base.userids[0].certifications.is_empty());
4623 assert!(cert_donald_signs_base.userids[0].certifications.len() == 1);
4624
4625 let merged = cert_donald_signs_base.clone()
4626 .merge_public_and_secret(cert_ivanka_signs_base.clone()).unwrap();
4627 assert!(merged.userids.len() == 1);
4628 assert!(merged.userids[0].self_signatures().count() == 1);
4629 assert!(merged.userids[0].certifications.len() == 2);
4630
4631 let merged = cert_donald_signs_base.clone()
4632 .merge_public_and_secret(cert_donald_signs_all.clone()).unwrap();
4633 assert!(merged.userids.len() == 3);
4634 assert!(merged.userids[0].self_signatures().count() == 1);
4635 // There should be two certifications from the Donald on the
4636 // first user id.
4637 assert!(merged.userids[0].certifications.len() == 2);
4638 assert!(merged.userids[1].certifications.len() == 1);
4639 assert!(merged.userids[2].certifications.len() == 1);
4640
4641 let merged = cert_donald_signs_base.clone()
4642 .merge_public_and_secret(cert_donald_signs_all.clone()).unwrap()
4643 .merge_public_and_secret(cert_ivanka_signs_base.clone()).unwrap()
4644 .merge_public_and_secret(cert_ivanka_signs_all.clone()).unwrap();
4645 assert!(merged.userids.len() == 3);
4646 assert!(merged.userids[0].self_signatures().count() == 1);
4647 // There should be two certifications from each of the Donald
4648 // and Ivanka on the first user id, and one each on the rest.
4649 assert!(merged.userids[0].certifications.len() == 4);
4650 assert!(merged.userids[1].certifications.len() == 2);
4651 assert!(merged.userids[2].certifications.len() == 2);
4652
4653 // Same as above, but redundant.
4654 let merged = cert_donald_signs_base.clone()
4655 .merge_public_and_secret(cert_ivanka_signs_base.clone()).unwrap()
4656 .merge_public_and_secret(cert_donald_signs_all.clone()).unwrap()
4657 .merge_public_and_secret(cert_donald_signs_all.clone()).unwrap()
4658 .merge_public_and_secret(cert_ivanka_signs_all.clone()).unwrap()
4659 .merge_public_and_secret(cert_ivanka_signs_base.clone()).unwrap()
4660 .merge_public_and_secret(cert_donald_signs_all.clone()).unwrap()
4661 .merge_public_and_secret(cert_donald_signs_all.clone()).unwrap()
4662 .merge_public_and_secret(cert_ivanka_signs_all.clone()).unwrap();
4663 assert!(merged.userids.len() == 3);
4664 assert!(merged.userids[0].self_signatures().count() == 1);
4665 // There should be two certifications from each of the Donald
4666 // and Ivanka on the first user id, and one each on the rest.
4667 assert!(merged.userids[0].certifications.len() == 4);
4668 assert!(merged.userids[1].certifications.len() == 2);
4669 assert!(merged.userids[2].certifications.len() == 2);
4670 }
4671
4672 #[test]
4673 fn out_of_order_self_sigs_test() {
4674 // neal-out-of-order.pgp contains all the self-signatures,
4675 // but some are out of order. The canonicalization step
4676 // should reorder them.
4677 //
4678 // original order/new order:
4679 //
4680 // 1/ 1. pk
4681 // 2/ 2. user id #1: neal@walfield.org (good)
4682 // 3/ 3. sig over user ID #1
4683 //
4684 // 4/ 4. user id #2: neal@gnupg.org (good)
4685 // 5/ 7. sig over user ID #3
4686 // 6/ 5. sig over user ID #2
4687 //
4688 // 7/ 6. user id #3: neal@g10code.com (bad)
4689 //
4690 // 8/ 8. user ID #4: neal@pep.foundation (bad)
4691 // 9/11. sig over user ID #5
4692 //
4693 // 10/10. user id #5: neal@pep-project.org (bad)
4694 // 11/ 9. sig over user ID #4
4695 //
4696 // 12/12. user ID #6: neal@sequoia-pgp.org (good)
4697 // 13/13. sig over user ID #6
4698 //
4699 // ----------------------------------------------
4700 //
4701 // 14/14. signing subkey #1: 7223B56678E02528 (good)
4702 // 15/15. sig over subkey #1
4703 // 16/16. sig over subkey #1
4704 //
4705 // 17/17. encryption subkey #2: C2B819056C652598 (good)
4706 // 18/18. sig over subkey #2
4707 // 19/21. sig over subkey #3
4708 // 20/22. sig over subkey #3
4709 //
4710 // 21/20. auth subkey #3: A3506AFB820ABD08 (bad)
4711 // 22/19. sig over subkey #2
4712
4713 let cert = Cert::from_bytes(crate::tests::key("neal-sigs-out-of-order.pgp"))
4714 .unwrap();
4715
4716 let mut userids = cert.userids()
4717 .map(|u| String::from_utf8_lossy(u.userid().value()).into_owned())
4718 .collect::<Vec<String>>();
4719 userids.sort();
4720
4721 assert_eq!(userids,
4722 &[ "Neal H. Walfield <neal@g10code.com>",
4723 "Neal H. Walfield <neal@gnupg.org>",
4724 "Neal H. Walfield <neal@pep-project.org>",
4725 "Neal H. Walfield <neal@pep.foundation>",
4726 "Neal H. Walfield <neal@sequoia-pgp.org>",
4727 "Neal H. Walfield <neal@walfield.org>",
4728 ]);
4729
4730 let mut subkeys = cert.subkeys()
4731 .map(|sk| Some(sk.key().keyid()))
4732 .collect::<Vec<Option<KeyID>>>();
4733 subkeys.sort();
4734 assert_eq!(subkeys,
4735 &[ "7223B56678E02528".parse().ok(),
4736 "A3506AFB820ABD08".parse().ok(),
4737 "C2B819056C652598".parse().ok(),
4738 ]);
4739
4740 // DKG's key has all the self-signatures moved to the last
4741 // subkey; all user ids/user attributes/subkeys have nothing.
4742 let cert =
4743 Cert::from_bytes(crate::tests::key("dkg-sigs-out-of-order.pgp")).unwrap();
4744
4745 let mut userids = cert.userids()
4746 .map(|u| String::from_utf8_lossy(u.userid().value()).into_owned())
4747 .collect::<Vec<String>>();
4748 userids.sort();
4749
4750 assert_eq!(userids,
4751 &[ "Daniel Kahn Gillmor <dkg-debian.org@fifthhorseman.net>",
4752 "Daniel Kahn Gillmor <dkg@aclu.org>",
4753 "Daniel Kahn Gillmor <dkg@astro.columbia.edu>",
4754 "Daniel Kahn Gillmor <dkg@debian.org>",
4755 "Daniel Kahn Gillmor <dkg@fifthhorseman.net>",
4756 "Daniel Kahn Gillmor <dkg@openflows.com>",
4757 ]);
4758
4759 assert_eq!(cert.user_attributes.len(), 1);
4760
4761 let mut subkeys = cert.subkeys()
4762 .map(|sk| Some(sk.key().keyid()))
4763 .collect::<Vec<Option<KeyID>>>();
4764 subkeys.sort();
4765 assert_eq!(subkeys,
4766 &[ "1075 8EBD BD7C FAB5".parse().ok(),
4767 "1258 68EA 4BFA 08E4".parse().ok(),
4768 "1498 ADC6 C192 3237".parse().ok(),
4769 "24EC FF5A FF68 370A".parse().ok(),
4770 "3714 7292 14D5 DA70".parse().ok(),
4771 "3B7A A7F0 14E6 9B5A".parse().ok(),
4772 "5B58 DCF9 C341 6611".parse().ok(),
4773 "A524 01B1 1BFD FA5C".parse().ok(),
4774 "A70A 96E1 439E A852".parse().ok(),
4775 "C61B D3EC 2148 4CFF".parse().ok(),
4776 "CAEF A883 2167 5333".parse().ok(),
4777 "DC10 4C4E 0CA7 57FB".parse().ok(),
4778 "E3A3 2229 449B 0350".parse().ok(),
4779 ]);
4780
4781 }
4782
4783 /// Tests how we deal with v3 keys, certs, and certifications.
4784 #[test]
4785 fn v3_packets() {
4786 // v3 primary keys are not supported.
4787
4788 let cert = Cert::from_bytes(crate::tests::key("john-v3.pgp"));
4789 assert_match!(Error::UnsupportedCert(..)
4790 = cert.err().unwrap().downcast::<Error>().unwrap());
4791
4792 let cert = Cert::from_bytes(crate::tests::key("john-v3-secret.pgp"));
4793 assert_match!(Error::UnsupportedCert(..)
4794 = cert.err().unwrap().downcast::<Error>().unwrap());
4795
4796 // Lutz's key is a v3 key.
4797 let cert = Cert::from_bytes(crate::tests::key("lutz.pgp"));
4798 assert_match!(Error::UnsupportedCert(..)
4799 = cert.err().unwrap().downcast::<Error>().unwrap());
4800
4801 // v3 certifications are not supported
4802
4803 // dkg's includes some v3 signatures.
4804 let cert = Cert::from_bytes(crate::tests::key("dkg.pgp"));
4805 assert!(cert.is_ok(), "dkg.pgp: {:?}", cert);
4806 }
4807
4808 #[test]
4809 fn keyring_with_v3_public_keys() {
4810 let dkg = crate::tests::key("dkg.pgp");
4811 let lutz = crate::tests::key("lutz.pgp");
4812
4813 let cert = Cert::from_bytes(dkg);
4814 assert!(cert.is_ok(), "dkg.pgp: {:?}", cert);
4815
4816 // Keyring with two good keys
4817 let mut combined = vec![];
4818 combined.extend_from_slice(dkg);
4819 combined.extend_from_slice(dkg);
4820 let certs = CertParser::from_bytes(&combined[..]).unwrap()
4821 .map(|certr| certr.is_ok())
4822 .collect::<Vec<bool>>();
4823 assert_eq!(certs, &[ true, true ]);
4824
4825 // Keyring with a good key, and a bad key.
4826 let mut combined = vec![];
4827 combined.extend_from_slice(dkg);
4828 combined.extend_from_slice(lutz);
4829 let certs = CertParser::from_bytes(&combined[..]).unwrap()
4830 .map(|certr| certr.is_ok())
4831 .collect::<Vec<bool>>();
4832 assert_eq!(certs, &[ true, false ]);
4833
4834 // Keyring with a bad key, and a good key.
4835 let mut combined = vec![];
4836 combined.extend_from_slice(lutz);
4837 combined.extend_from_slice(dkg);
4838 let certs = CertParser::from_bytes(&combined[..]).unwrap()
4839 .map(|certr| certr.is_ok())
4840 .collect::<Vec<bool>>();
4841 assert_eq!(certs, &[ false, true ]);
4842
4843 // Keyring with a good key, a bad key, and a good key.
4844 let mut combined = vec![];
4845 combined.extend_from_slice(dkg);
4846 combined.extend_from_slice(lutz);
4847 combined.extend_from_slice(dkg);
4848 let certs = CertParser::from_bytes(&combined[..]).unwrap()
4849 .map(|certr| certr.is_ok())
4850 .collect::<Vec<bool>>();
4851 assert_eq!(certs, &[ true, false, true ]);
4852
4853 // Keyring with a good key, a bad key, and a bad key.
4854 let mut combined = vec![];
4855 combined.extend_from_slice(dkg);
4856 combined.extend_from_slice(lutz);
4857 combined.extend_from_slice(lutz);
4858 let certs = CertParser::from_bytes(&combined[..]).unwrap()
4859 .map(|certr| certr.is_ok())
4860 .collect::<Vec<bool>>();
4861 assert_eq!(certs, &[ true, false, false ]);
4862
4863 // Keyring with a good key, a bad key, a bad key, and a good key.
4864 let mut combined = vec![];
4865 combined.extend_from_slice(dkg);
4866 combined.extend_from_slice(lutz);
4867 combined.extend_from_slice(lutz);
4868 combined.extend_from_slice(dkg);
4869 let certs = CertParser::from_bytes(&combined[..]).unwrap()
4870 .map(|certr| certr.is_ok())
4871 .collect::<Vec<bool>>();
4872 assert_eq!(certs, &[ true, false, false, true ]);
4873 }
4874
4875 #[test]
4876 fn merge_with_incomplete_update() {
4877 let p = &P::new();
4878
4879 let cert = Cert::from_bytes(crate::tests::key("about-to-expire.expired.pgp"))
4880 .unwrap();
4881 cert.primary_key().with_policy(p, None).unwrap().alive().unwrap_err();
4882
4883 let update =
4884 Cert::from_bytes(crate::tests::key("about-to-expire.update-no-uid.pgp"))
4885 .unwrap();
4886 let cert = cert.merge_public_and_secret(update).unwrap();
4887 cert.primary_key().with_policy(p, None).unwrap().alive().unwrap();
4888 }
4889
4890 #[test]
4891 fn packet_pile_roundtrip() {
4892 // Make sure Cert::try_from(Cert::to_packet_pile(cert))
4893 // does a clean round trip.
4894
4895 let cert = Cert::from_bytes(crate::tests::key("already-revoked.pgp")).unwrap();
4896 let cert2
4897 = Cert::try_from(cert.clone().into_packet_pile()).unwrap();
4898 assert_eq!(cert, cert2);
4899
4900 let cert = Cert::from_bytes(
4901 crate::tests::key("already-revoked-direct-revocation.pgp")).unwrap();
4902 let cert2
4903 = Cert::try_from(cert.clone().into_packet_pile()).unwrap();
4904 assert_eq!(cert, cert2);
4905
4906 let cert = Cert::from_bytes(
4907 crate::tests::key("already-revoked-userid-revocation.pgp")).unwrap();
4908 let cert2
4909 = Cert::try_from(cert.clone().into_packet_pile()).unwrap();
4910 assert_eq!(cert, cert2);
4911
4912 let cert = Cert::from_bytes(
4913 crate::tests::key("already-revoked-subkey-revocation.pgp")).unwrap();
4914 let cert2
4915 = Cert::try_from(cert.clone().into_packet_pile()).unwrap();
4916 assert_eq!(cert, cert2);
4917 }
4918
4919 #[test]
4920 fn insert_packets_add_sig() {
4921 use crate::armor;
4922 use crate::packet::Tag;
4923
4924 // Merge the revocation certificate into the Cert and make sure
4925 // it shows up.
4926 let cert = Cert::from_bytes(crate::tests::key("already-revoked.pgp")).unwrap();
4927
4928 let rev = crate::tests::key("already-revoked.rev");
4929 let rev = PacketPile::from_reader(armor::Reader::from_reader(rev, None))
4930 .unwrap();
4931
4932 let rev : Vec<Packet> = rev.into_children().collect();
4933 assert_eq!(rev.len(), 1);
4934 assert_eq!(rev[0].tag(), Tag::Signature);
4935
4936 let packets_pre_merge = cert.clone().into_packets().count();
4937 let cert = cert.insert_packets(rev).unwrap().0;
4938 let packets_post_merge = cert.clone().into_packets().count();
4939 assert_eq!(packets_post_merge, packets_pre_merge + 1);
4940 }
4941
4942 #[test]
4943 fn insert_packets_update_sig() -> Result<()> {
4944 use std::time::Duration;
4945
4946 use crate::packet::signature::subpacket::Subpacket;
4947 use crate::packet::signature::subpacket::SubpacketValue;
4948
4949 let (cert, _) = CertBuilder::general_purpose(Some("Test"))
4950 .generate()?;
4951 let packets = cert.clone().into_packets().count();
4952
4953 // Merge a signature with different unhashed subpacket areas.
4954 // Make sure only the last variant is merged.
4955 let sig = cert.primary_key().self_signatures().next()
4956 .expect("binding signature");
4957
4958 let a = Subpacket::new(
4959 SubpacketValue::SignatureExpirationTime(
4960 Duration::new(1, 0).try_into()?),
4961 false)?;
4962 let b = Subpacket::new(
4963 SubpacketValue::SignatureExpirationTime(
4964 Duration::new(2, 0).try_into()?),
4965 false)?;
4966
4967 let mut sig_a = sig.clone();
4968 sig_a.unhashed_area_mut().add(a)?;
4969 let mut sig_b = sig.clone();
4970 sig_b.unhashed_area_mut().add(b)?;
4971
4972 // Insert sig_a, make sure it (and it alone) appears.
4973 let cert2 = cert.clone().insert_packets(sig_a.clone())?.0;
4974 let mut sigs = cert2.primary_key().self_signatures();
4975 assert_eq!(sigs.next(), Some(&sig_a));
4976 assert!(sigs.next().is_none());
4977 assert_eq!(cert2.clone().into_packets().count(), packets);
4978
4979 // Insert sig_b, make sure it (and it alone) appears.
4980 let cert2 = cert.clone().insert_packets(sig_b.clone())?.0;
4981 let mut sigs = cert2.primary_key().self_signatures();
4982 assert_eq!(sigs.next(), Some(&sig_b));
4983 assert!(sigs.next().is_none());
4984 assert_eq!(cert2.clone().into_packets().count(), packets);
4985
4986 // Insert sig_a and sig_b. Make sure sig_b (and it alone)
4987 // appears.
4988 let cert2 = cert.clone().insert_packets(
4989 vec![ sig_a.clone(), sig_b.clone() ])?.0;
4990 let mut sigs = cert2.primary_key().self_signatures();
4991 assert_eq!(sigs.next(), Some(&sig_b));
4992 assert!(sigs.next().is_none());
4993 assert_eq!(cert2.clone().into_packets().count(), packets);
4994
4995 // Insert sig_b and sig_a. Make sure sig_a (and it alone)
4996 // appears.
4997 let cert2 = cert.clone().insert_packets(
4998 vec![ sig_b.clone(), sig_a.clone() ])?.0;
4999 let mut sigs = cert2.primary_key().self_signatures();
5000 assert_eq!(sigs.next(), Some(&sig_a));
5001 assert!(sigs.next().is_none());
5002 assert_eq!(cert2.clone().into_packets().count(), packets);
5003
5004 Ok(())
5005 }
5006
5007 #[test]
5008 fn insert_packets_add_userid() -> Result<()> {
5009 let (cert, _) = CertBuilder::general_purpose(Some("a"))
5010 .generate()?;
5011 let packets = cert.clone().into_packets().count();
5012
5013 let uid_a = UserID::from("a");
5014 let uid_b = UserID::from("b");
5015
5016 // Insert a, make sure it appears once.
5017 let cert2 = cert.clone().insert_packets(uid_a.clone())?.0;
5018 let mut uids = cert2.userids();
5019 assert_eq!(uids.next().unwrap().userid(), &uid_a);
5020 assert!(uids.next().is_none());
5021 assert_eq!(cert2.clone().into_packets().count(), packets);
5022
5023 // Insert b, make sure it also appears.
5024 let cert2 = cert.clone().insert_packets(uid_b.clone())?.0;
5025 let mut uids: Vec<UserID>
5026 = cert2.userids().map(|ua| ua.userid().clone()).collect();
5027 uids.sort();
5028 let mut uids = uids.iter();
5029 assert_eq!(uids.next().unwrap(), &uid_a);
5030 assert_eq!(uids.next().unwrap(), &uid_b);
5031 assert!(uids.next().is_none());
5032 assert_eq!(cert2.clone().into_packets().count(), packets + 1);
5033
5034 Ok(())
5035 }
5036
5037 #[test]
5038 fn insert_packets_update_key() -> Result<()> {
5039 use crate::crypto::Password;
5040
5041 let (cert, _) = CertBuilder::new().generate()?;
5042 let packets = cert.clone().into_packets().count();
5043 assert_eq!(cert.keys().count(), 1);
5044
5045 let key = cert.keys().secret().next().unwrap().key()
5046 .role_as_primary();
5047 assert!(key.has_secret());
5048 let key_a = key.clone().encrypt_secret(&Password::from("a"))?;
5049 let key_b = key.clone().encrypt_secret(&Password::from("b"))?;
5050
5051 // Insert variant a.
5052 let cert2 = cert.clone().insert_packets(key_a.clone())?.0;
5053 assert_eq!(cert2.primary_key().key().parts_as_secret().unwrap(),
5054 &key_a);
5055 assert_eq!(cert2.clone().into_packets().count(), packets);
5056
5057 // Insert variant b.
5058 let cert2 = cert.clone().insert_packets(key_b.clone())?.0;
5059 assert_eq!(cert2.primary_key().key().parts_as_secret().unwrap(),
5060 &key_b);
5061 assert_eq!(cert2.clone().into_packets().count(), packets);
5062
5063 // Insert variant a then b. We should keep b.
5064 let cert2 = cert.clone().insert_packets(
5065 vec![ key_a.clone(), key_b.clone() ])?.0;
5066 assert_eq!(cert2.primary_key().key().parts_as_secret().unwrap(),
5067 &key_b);
5068 assert_eq!(cert2.clone().into_packets().count(), packets);
5069
5070 // Insert variant b then a. We should keep a.
5071 let cert2 = cert.clone().insert_packets(
5072 vec![ key_b.clone(), key_a.clone() ])?.0;
5073 assert_eq!(cert2.primary_key().key().parts_as_secret().unwrap(),
5074 &key_a);
5075 assert_eq!(cert2.clone().into_packets().count(), packets);
5076
5077 Ok(())
5078 }
5079
5080 #[test]
5081 fn set_validity_period() {
5082 let p = &P::new();
5083
5084 let (cert, _) = CertBuilder::general_purpose(Some("Test"))
5085 .generate().unwrap();
5086 assert_eq!(cert.clone().into_packet_pile().children().count(),
5087 1 // primary key
5088 + 1 // direct key signature
5089 + 1 // userid
5090 + 1 // binding signature
5091 + 1 // subkey
5092 + 1 // binding signature
5093 + 1 // subkey
5094 + 1 // binding signature
5095 );
5096 let cert = check_set_validity_period(p, cert);
5097 assert_eq!(cert.clone().into_packet_pile().children().count(),
5098 1 // primary key
5099 + 1 // direct key signature
5100 + 2 // two new direct key signatures
5101 + 1 // userid
5102 + 1 // binding signature
5103 + 2 // two new binding signatures
5104 + 1 // subkey
5105 + 1 // binding signature
5106 + 1 // subkey
5107 + 1 // binding signature
5108 );
5109 }
5110
5111 #[test]
5112 fn set_validity_period_two_uids() -> Result<()> {
5113 use quickcheck::{Arbitrary, Gen};
5114 let mut gen = Gen::new(16);
5115 let p = &P::new();
5116
5117 let userid1 = UserID::arbitrary(&mut gen);
5118 // The two user ids need to be unique.
5119 let mut userid2 = UserID::arbitrary(&mut gen);
5120 while userid1 == userid2 {
5121 userid2 = UserID::arbitrary(&mut gen);
5122 }
5123
5124 let (cert, _) = CertBuilder::general_purpose(
5125 Some(userid1))
5126 .add_userid(userid2)
5127 .generate()?;
5128 let primary_uid = cert.with_policy(p, None)?.primary_userid()?.userid().clone();
5129 assert_eq!(cert.clone().into_packet_pile().children().count(),
5130 1 // primary key
5131 + 1 // direct key signature
5132 + 1 // userid
5133 + 1 // binding signature
5134 + 1 // userid
5135 + 1 // binding signature
5136 + 1 // subkey
5137 + 1 // binding signature
5138 + 1 // subkey
5139 + 1 // binding signature
5140 );
5141 let cert = check_set_validity_period(p, cert);
5142 assert_eq!(cert.clone().into_packet_pile().children().count(),
5143 1 // primary key
5144 + 1 // direct key signature
5145 + 2 // two new direct key signatures
5146 + 1 // userid
5147 + 1 // binding signature
5148 + 2 // two new binding signatures
5149 + 1 // userid
5150 + 1 // binding signature
5151 + 2 // two new binding signatures
5152 + 1 // subkey
5153 + 1 // binding signature
5154 + 1 // subkey
5155 + 1 // binding signature
5156 );
5157 assert_eq!(&primary_uid, cert.with_policy(p, None)?.primary_userid()?.userid());
5158 Ok(())
5159 }
5160
5161 #[test]
5162 fn set_validity_period_uidless() {
5163 use crate::types::Duration;
5164 let p = &P::new();
5165
5166 let (cert, _) = CertBuilder::new()
5167 .set_validity_period(None) // Just to assert this works.
5168 .set_validity_period(Some(Duration::weeks(52).unwrap().try_into().unwrap()))
5169 .generate().unwrap();
5170 assert_eq!(cert.clone().into_packet_pile().children().count(),
5171 1 // primary key
5172 + 1 // direct key signature
5173 );
5174 let cert = check_set_validity_period(p, cert);
5175 assert_eq!(cert.clone().into_packet_pile().children().count(),
5176 1 // primary key
5177 + 1 // direct key signature
5178 + 2 // two new direct key signatures
5179 );
5180 }
5181 fn check_set_validity_period(policy: &dyn Policy, cert: Cert) -> Cert {
5182 let now = cert.primary_key().key().creation_time();
5183 let a_sec = time::Duration::new(1, 0);
5184
5185 let expiry_orig = cert.primary_key().with_policy(policy, now).unwrap()
5186 .key_validity_period()
5187 .expect("Keys expire by default.");
5188
5189 let mut keypair = cert.primary_key().key().clone().parts_into_secret()
5190 .unwrap().into_keypair().unwrap();
5191
5192 // Clear the expiration.
5193 let as_of1 = now + time::Duration::new(10, 0);
5194 let cert = cert.set_validity_period_as_of(
5195 policy, &mut keypair, None, as_of1).unwrap();
5196 {
5197 // If t < as_of1, we should get the original expiry.
5198 assert_eq!(cert.primary_key().with_policy(policy, now).unwrap()
5199 .key_validity_period(),
5200 Some(expiry_orig));
5201 assert_eq!(cert.primary_key().with_policy(policy, as_of1 - a_sec).unwrap()
5202 .key_validity_period(),
5203 Some(expiry_orig));
5204 // If t >= as_of1, we should get the new expiry.
5205 assert_eq!(cert.primary_key().with_policy(policy, as_of1).unwrap()
5206 .key_validity_period(),
5207 None);
5208 }
5209
5210 // Shorten the expiry. (The default expiration should be at
5211 // least a few weeks, so removing an hour should still keep us
5212 // over 0.)
5213 let expiry_new = expiry_orig - time::Duration::new(60 * 60, 0);
5214 assert!(expiry_new > time::Duration::new(0, 0));
5215
5216 let as_of2 = as_of1 + time::Duration::new(10, 0);
5217 let cert = cert.set_validity_period_as_of(
5218 policy, &mut keypair, Some(expiry_new), as_of2).unwrap();
5219 {
5220 // If t < as_of1, we should get the original expiry.
5221 assert_eq!(cert.primary_key().with_policy(policy, now).unwrap()
5222 .key_validity_period(),
5223 Some(expiry_orig));
5224 assert_eq!(cert.primary_key().with_policy(policy, as_of1 - a_sec).unwrap()
5225 .key_validity_period(),
5226 Some(expiry_orig));
5227 // If as_of1 <= t < as_of2, we should get the second
5228 // expiry (None).
5229 assert_eq!(cert.primary_key().with_policy(policy, as_of1).unwrap()
5230 .key_validity_period(),
5231 None);
5232 assert_eq!(cert.primary_key().with_policy(policy, as_of2 - a_sec).unwrap()
5233 .key_validity_period(),
5234 None);
5235 // If t <= as_of2, we should get the new expiry.
5236 assert_eq!(cert.primary_key().with_policy(policy, as_of2).unwrap()
5237 .key_validity_period(),
5238 Some(expiry_new));
5239 }
5240 cert
5241 }
5242
5243 #[test]
5244 fn direct_key_sig() {
5245 use crate::types::SignatureType;
5246 // XXX: testing sequoia against itself isn't optimal, but I couldn't
5247 // find a tool to generate direct key signatures :-(
5248
5249 let p = &P::new();
5250
5251 let (cert1, _) = CertBuilder::new().generate().unwrap();
5252 let mut buf = Vec::default();
5253
5254 cert1.serialize(&mut buf).unwrap();
5255 let cert2 = Cert::from_bytes(&buf).unwrap();
5256
5257 assert_eq!(
5258 cert2.primary_key().with_policy(p, None).unwrap()
5259 .direct_key_signature().unwrap().typ(),
5260 SignatureType::DirectKey);
5261 assert_eq!(cert2.userids().count(), 0);
5262 }
5263
5264 #[test]
5265 fn revoked() {
5266 fn check(cert: &Cert, direct_revoked: bool,
5267 userid_revoked: bool, subkey_revoked: bool) {
5268 let p = &P::new();
5269
5270 // If we have a user id---even if it is revoked---we have
5271 // a primary key signature.
5272 let typ = cert.primary_key().with_policy(p, None).unwrap()
5273 .binding_signature().typ();
5274 assert_eq!(typ, SignatureType::PositiveCertification,
5275 "{:#?}", cert);
5276
5277 let revoked = cert.revocation_status(p, None);
5278 if direct_revoked {
5279 assert_match!(RevocationStatus::Revoked(_) = revoked,
5280 "{:#?}", cert);
5281 } else {
5282 assert_eq!(revoked, RevocationStatus::NotAsFarAsWeKnow,
5283 "{:#?}", cert);
5284 }
5285
5286 for userid in cert.userids().with_policy(p, None) {
5287 let typ = userid.binding_signature().typ();
5288 assert_eq!(typ, SignatureType::PositiveCertification,
5289 "{:#?}", cert);
5290
5291 let revoked = userid.revocation_status();
5292 if userid_revoked {
5293 assert_match!(RevocationStatus::Revoked(_) = revoked);
5294 } else {
5295 assert_eq!(RevocationStatus::NotAsFarAsWeKnow, revoked,
5296 "{:#?}", cert);
5297 }
5298 }
5299
5300 for subkey in cert.subkeys() {
5301 let typ = subkey.binding_signature(p, None).unwrap().typ();
5302 assert_eq!(typ, SignatureType::SubkeyBinding,
5303 "{:#?}", cert);
5304
5305 let revoked = subkey.revocation_status(p, None);
5306 if subkey_revoked {
5307 assert_match!(RevocationStatus::Revoked(_) = revoked);
5308 } else {
5309 assert_eq!(RevocationStatus::NotAsFarAsWeKnow, revoked,
5310 "{:#?}", cert);
5311 }
5312 }
5313 }
5314
5315 let cert = Cert::from_bytes(crate::tests::key("already-revoked.pgp")).unwrap();
5316 check(&cert, false, false, false);
5317
5318 let d = Cert::from_bytes(
5319 crate::tests::key("already-revoked-direct-revocation.pgp")).unwrap();
5320 check(&d, true, false, false);
5321
5322 check(&cert.clone().merge_public_and_secret(d.clone()).unwrap(), true, false, false);
5323 // Make sure the merge order does not matter.
5324 check(&d.clone().merge_public_and_secret(cert.clone()).unwrap(), true, false, false);
5325
5326 let u = Cert::from_bytes(
5327 crate::tests::key("already-revoked-userid-revocation.pgp")).unwrap();
5328 check(&u, false, true, false);
5329
5330 check(&cert.clone().merge_public_and_secret(u.clone()).unwrap(), false, true, false);
5331 check(&u.clone().merge_public_and_secret(cert.clone()).unwrap(), false, true, false);
5332
5333 let k = Cert::from_bytes(
5334 crate::tests::key("already-revoked-subkey-revocation.pgp")).unwrap();
5335 check(&k, false, false, true);
5336
5337 check(&cert.clone().merge_public_and_secret(k.clone()).unwrap(), false, false, true);
5338 check(&k.clone().merge_public_and_secret(cert.clone()).unwrap(), false, false, true);
5339
5340 // direct and user id revocation.
5341 check(&d.clone().merge_public_and_secret(u.clone()).unwrap(), true, true, false);
5342 check(&u.clone().merge_public_and_secret(d.clone()).unwrap(), true, true, false);
5343
5344 // direct and subkey revocation.
5345 check(&d.clone().merge_public_and_secret(k.clone()).unwrap(), true, false, true);
5346 check(&k.clone().merge_public_and_secret(d.clone()).unwrap(), true, false, true);
5347
5348 // user id and subkey revocation.
5349 check(&u.clone().merge_public_and_secret(k.clone()).unwrap(), false, true, true);
5350 check(&k.clone().merge_public_and_secret(u.clone()).unwrap(), false, true, true);
5351
5352 // direct, user id and subkey revocation.
5353 check(&d.clone().merge_public_and_secret(u.clone().merge_public_and_secret(k.clone()).unwrap()).unwrap(),
5354 true, true, true);
5355 check(&d.clone().merge_public_and_secret(k.clone().merge_public_and_secret(u.clone()).unwrap()).unwrap(),
5356 true, true, true);
5357 }
5358
5359 #[test]
5360 fn revoke() {
5361 let p = &P::new();
5362
5363 let (cert, _) = CertBuilder::general_purpose(Some("Test"))
5364 .generate().unwrap();
5365 assert_eq!(RevocationStatus::NotAsFarAsWeKnow,
5366 cert.revocation_status(p, None));
5367
5368 let mut keypair = cert.primary_key().key().clone().parts_into_secret()
5369 .unwrap().into_keypair().unwrap();
5370
5371 let sig = CertRevocationBuilder::new()
5372 .set_reason_for_revocation(
5373 ReasonForRevocation::KeyCompromised,
5374 b"It was the maid :/").unwrap()
5375 .build(&mut keypair, &cert, None)
5376 .unwrap();
5377 assert_eq!(sig.typ(), SignatureType::KeyRevocation);
5378 assert_eq!(sig.issuers().collect::<Vec<_>>(),
5379 vec![ &cert.keyid() ]);
5380 assert_eq!(sig.issuer_fingerprints().collect::<Vec<_>>(),
5381 vec![ &cert.fingerprint() ]);
5382
5383 let cert = cert.insert_packets(sig).unwrap().0;
5384 assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, None));
5385
5386
5387 // Have other revoke cert.
5388 let (other, _) = CertBuilder::general_purpose(Some("Test 2"))
5389 .generate().unwrap();
5390
5391 let mut keypair = other.primary_key().key().clone().parts_into_secret()
5392 .unwrap().into_keypair().unwrap();
5393
5394 let sig = CertRevocationBuilder::new()
5395 .set_reason_for_revocation(
5396 ReasonForRevocation::KeyCompromised,
5397 b"It was the maid :/").unwrap()
5398 .build(&mut keypair, &cert, None)
5399 .unwrap();
5400
5401 assert_eq!(sig.typ(), SignatureType::KeyRevocation);
5402 assert_eq!(sig.issuers().collect::<Vec<_>>(),
5403 vec![ &other.keyid() ]);
5404 assert_eq!(sig.issuer_fingerprints().collect::<Vec<_>>(),
5405 vec![ &other.fingerprint() ]);
5406 }
5407
5408 #[test]
5409 fn revoke_subkey() {
5410 let p = &P::new();
5411 let (cert, _) = CertBuilder::new()
5412 .add_transport_encryption_subkey()
5413 .generate().unwrap();
5414
5415 let sig = {
5416 let subkey = cert.subkeys().next().unwrap();
5417 assert_eq!(RevocationStatus::NotAsFarAsWeKnow,
5418 subkey.revocation_status(p, None));
5419
5420 let mut keypair = cert.primary_key().key().clone().parts_into_secret()
5421 .unwrap().into_keypair().unwrap();
5422 SubkeyRevocationBuilder::new()
5423 .set_reason_for_revocation(
5424 ReasonForRevocation::UIDRetired,
5425 b"It was the maid :/").unwrap()
5426 .build(&mut keypair, &cert, subkey.key(), None)
5427 .unwrap()
5428 };
5429 assert_eq!(sig.typ(), SignatureType::SubkeyRevocation);
5430 let cert = cert.insert_packets(sig).unwrap().0;
5431 assert_eq!(RevocationStatus::NotAsFarAsWeKnow,
5432 cert.revocation_status(p, None));
5433
5434 let subkey = cert.subkeys().next().unwrap();
5435 assert_match!(RevocationStatus::Revoked(_)
5436 = subkey.revocation_status(p, None));
5437 }
5438
5439 #[test]
5440 fn revoke_uid() {
5441 let p = &P::new();
5442 let (cert, _) = CertBuilder::new()
5443 .add_userid("Test1")
5444 .add_userid("Test2")
5445 .generate().unwrap();
5446
5447 let sig = {
5448 let uid = cert.userids().with_policy(p, None).nth(1).unwrap();
5449 assert_eq!(RevocationStatus::NotAsFarAsWeKnow, uid.revocation_status());
5450
5451 let mut keypair = cert.primary_key().key().clone().parts_into_secret()
5452 .unwrap().into_keypair().unwrap();
5453 UserIDRevocationBuilder::new()
5454 .set_reason_for_revocation(
5455 ReasonForRevocation::UIDRetired,
5456 b"It was the maid :/").unwrap()
5457 .build(&mut keypair, &cert, uid.userid(), None)
5458 .unwrap()
5459 };
5460 assert_eq!(sig.typ(), SignatureType::CertificationRevocation);
5461 let cert = cert.insert_packets(sig).unwrap().0;
5462 assert_eq!(RevocationStatus::NotAsFarAsWeKnow,
5463 cert.revocation_status(p, None));
5464
5465 let uid = cert.userids().with_policy(p, None).nth(1).unwrap();
5466 assert_match!(RevocationStatus::Revoked(_) = uid.revocation_status());
5467 }
5468
5469 #[test]
5470 fn key_revoked() {
5471 use crate::types::Features;
5472 use crate::packet::key::Key6;
5473 use rand::{thread_rng, Rng, distributions::Open01};
5474
5475 let p = &P::new();
5476
5477 /*
5478 * t1: 1st binding sig ctime
5479 * t2: soft rev sig ctime
5480 * t3: 2nd binding sig ctime
5481 * t4: hard rev sig ctime
5482 *
5483 * [0,t1): invalid, but not revoked
5484 * [t1,t2): valid (not revocations)
5485 * [t2,t3): revoked (soft revocation)
5486 * [t3,t4): valid again (new self sig)
5487 * [t4,inf): hard revocation (hard revocation)
5488 *
5489 * Once the hard revocation is merged, then the Cert is
5490 * considered revoked at all times.
5491 */
5492 let t1 = time::UNIX_EPOCH + time::Duration::new(946681200, 0); // 2000-1-1
5493 let t2 = time::UNIX_EPOCH + time::Duration::new(978303600, 0); // 2001-1-1
5494 let t3 = time::UNIX_EPOCH + time::Duration::new(1009839600, 0); // 2002-1-1
5495 let t4 = time::UNIX_EPOCH + time::Duration::new(1041375600, 0); // 2003-1-1
5496
5497 let mut key: key::SecretKey
5498 = Key6::generate_ecc(true, Curve::Ed25519).unwrap().into();
5499 key.set_creation_time(t1).unwrap();
5500 let mut pair = key.clone().into_keypair().unwrap();
5501 let (bind1, rev1, bind2, rev2) = {
5502 let bind1 = signature::SignatureBuilder::new(SignatureType::DirectKey)
5503 .set_features(Features::sequoia()).unwrap()
5504 .set_key_flags(KeyFlags::empty()).unwrap()
5505 .set_signature_creation_time(t1).unwrap()
5506 .set_key_validity_period(Some(time::Duration::new(10 * 52 * 7 * 24 * 60 * 60, 0))).unwrap()
5507 .set_preferred_hash_algorithms(vec![HashAlgorithm::SHA512]).unwrap()
5508 .sign_direct_key(&mut pair, key.parts_as_public()).unwrap();
5509
5510 let rev1 = signature::SignatureBuilder::new(SignatureType::KeyRevocation)
5511 .set_signature_creation_time(t2).unwrap()
5512 .set_reason_for_revocation(ReasonForRevocation::KeySuperseded,
5513 &b""[..]).unwrap()
5514 .sign_direct_key(&mut pair, key.parts_as_public()).unwrap();
5515
5516 let bind2 = signature::SignatureBuilder::new(SignatureType::DirectKey)
5517 .set_features(Features::sequoia()).unwrap()
5518 .set_key_flags(KeyFlags::empty()).unwrap()
5519 .set_signature_creation_time(t3).unwrap()
5520 .set_key_validity_period(Some(time::Duration::new(10 * 52 * 7 * 24 * 60 * 60, 0))).unwrap()
5521 .set_preferred_hash_algorithms(vec![HashAlgorithm::SHA512]).unwrap()
5522 .sign_direct_key(&mut pair, key.parts_as_public()).unwrap();
5523
5524 let rev2 = signature::SignatureBuilder::new(SignatureType::KeyRevocation)
5525 .set_signature_creation_time(t4).unwrap()
5526 .set_reason_for_revocation(ReasonForRevocation::KeyCompromised,
5527 &b""[..]).unwrap()
5528 .sign_direct_key(&mut pair, key.parts_as_public()).unwrap();
5529
5530 (bind1, rev1, bind2, rev2)
5531 };
5532 let pk : key::PublicKey = key.into();
5533 let cert = Cert::try_from(vec![
5534 pk.into(),
5535 bind1.into(),
5536 bind2.into(),
5537 rev1.into()
5538 ]).unwrap();
5539
5540 let f1: f32 = thread_rng().sample(Open01);
5541 let f2: f32 = thread_rng().sample(Open01);
5542 let f3: f32 = thread_rng().sample(Open01);
5543 let f4: f32 = thread_rng().sample(Open01);
5544 let te1 = t1 - time::Duration::new((60. * 60. * 24. * 300.0 * f1) as u64, 0);
5545 let t12 = t1 + time::Duration::new((60. * 60. * 24. * 300.0 * f2) as u64, 0);
5546 let t23 = t2 + time::Duration::new((60. * 60. * 24. * 300.0 * f3) as u64, 0);
5547 let t34 = t3 + time::Duration::new((60. * 60. * 24. * 300.0 * f4) as u64, 0);
5548
5549 assert_eq!(cert.revocation_status(p, te1), RevocationStatus::NotAsFarAsWeKnow);
5550 assert_eq!(cert.revocation_status(p, t12), RevocationStatus::NotAsFarAsWeKnow);
5551 assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, t23));
5552 assert_eq!(cert.revocation_status(p, t34), RevocationStatus::NotAsFarAsWeKnow);
5553
5554 // Merge in the hard revocation.
5555 let cert = cert.insert_packets(rev2).unwrap().0;
5556 assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, te1));
5557 assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, t12));
5558 assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, t23));
5559 assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, t34));
5560 assert_match!(RevocationStatus::Revoked(_) = cert.revocation_status(p, t4));
5561 assert_match!(RevocationStatus::Revoked(_)
5562 = cert.revocation_status(p, crate::now()));
5563 }
5564
5565 #[test]
5566 fn key_revoked2() {
5567 tracer!(true, "cert_revoked2", 0);
5568
5569 let p = &P::new();
5570
5571 fn cert_revoked<T>(p: &dyn Policy, cert: &Cert, t: T) -> bool
5572 where T: Into<Option<time::SystemTime>>
5573 {
5574 !matches!(
5575 cert.revocation_status(p, t),
5576 RevocationStatus::NotAsFarAsWeKnow
5577 )
5578 }
5579
5580 fn subkey_revoked<T>(p: &dyn Policy, cert: &Cert, t: T) -> bool
5581 where T: Into<Option<time::SystemTime>>
5582 {
5583 !matches!(
5584 cert.subkeys().next().unwrap().bundle().revocation_status(p, t),
5585 RevocationStatus::NotAsFarAsWeKnow
5586 )
5587 }
5588
5589 let tests : [(&str, Box<dyn Fn(&dyn Policy, &Cert, _) -> bool>); 2] = [
5590 ("cert", Box::new(cert_revoked)),
5591 ("subkey", Box::new(subkey_revoked)),
5592 ];
5593
5594 for (f, revoked) in tests.iter()
5595 {
5596 t!("Checking {} revocation", f);
5597
5598 t!("Normal key");
5599 let cert = Cert::from_bytes(
5600 crate::tests::key(
5601 &format!("really-revoked-{}-0-public.pgp", f))).unwrap();
5602 let selfsig0 = cert.primary_key().with_policy(p, None).unwrap()
5603 .binding_signature().signature_creation_time().unwrap();
5604
5605 assert!(!revoked(p, &cert, Some(selfsig0)));
5606 assert!(!revoked(p, &cert, None));
5607
5608 t!("Soft revocation");
5609 let cert = cert.merge_public_and_secret(
5610 Cert::from_bytes(
5611 crate::tests::key(
5612 &format!("really-revoked-{}-1-soft-revocation.pgp", f))
5613 ).unwrap()).unwrap();
5614 // A soft revocation made after `t` is ignored when
5615 // determining whether the key is revoked at time `t`.
5616 assert!(!revoked(p, &cert, Some(selfsig0)));
5617 assert!(revoked(p, &cert, None));
5618
5619 t!("New self signature");
5620 let cert = cert.merge_public_and_secret(
5621 Cert::from_bytes(
5622 crate::tests::key(
5623 &format!("really-revoked-{}-2-new-self-sig.pgp", f))
5624 ).unwrap()).unwrap();
5625 assert!(!revoked(p, &cert, Some(selfsig0)));
5626 // Newer self-sig override older soft revocations.
5627 assert!(!revoked(p, &cert, None));
5628
5629 t!("Hard revocation");
5630 let cert = cert.merge_public_and_secret(
5631 Cert::from_bytes(
5632 crate::tests::key(
5633 &format!("really-revoked-{}-3-hard-revocation.pgp", f))
5634 ).unwrap()).unwrap();
5635 // Hard revocations trump all.
5636 assert!(revoked(p, &cert, Some(selfsig0)));
5637 assert!(revoked(p, &cert, None));
5638
5639 t!("New self signature");
5640 let cert = cert.merge_public_and_secret(
5641 Cert::from_bytes(
5642 crate::tests::key(
5643 &format!("really-revoked-{}-4-new-self-sig.pgp", f))
5644 ).unwrap()).unwrap();
5645 assert!(revoked(p, &cert, Some(selfsig0)));
5646 assert!(revoked(p, &cert, None));
5647 }
5648 }
5649
5650 #[test]
5651 fn userid_revoked2() {
5652 fn check_userids<T>(p: &dyn Policy, cert: &Cert, revoked: bool, t: T)
5653 where T: Into<Option<time::SystemTime>>, T: Copy
5654 {
5655 assert_match!(RevocationStatus::NotAsFarAsWeKnow
5656 = cert.revocation_status(p, None));
5657
5658 let mut slim_shady = false;
5659 let mut eminem = false;
5660 for b in cert.userids().with_policy(p, t) {
5661 if b.userid().value() == b"Slim Shady" {
5662 assert!(!slim_shady);
5663 slim_shady = true;
5664
5665 if revoked {
5666 assert_match!(RevocationStatus::Revoked(_)
5667 = b.revocation_status());
5668 } else {
5669 assert_match!(RevocationStatus::NotAsFarAsWeKnow
5670 = b.revocation_status());
5671 }
5672 } else {
5673 assert!(!eminem);
5674 eminem = true;
5675
5676 assert_match!(RevocationStatus::NotAsFarAsWeKnow
5677 = b.revocation_status());
5678 }
5679 }
5680
5681 assert!(slim_shady);
5682 assert!(eminem);
5683 }
5684
5685 fn check_uas<T>(p: &dyn Policy, cert: &Cert, revoked: bool, t: T)
5686 where T: Into<Option<time::SystemTime>>, T: Copy
5687 {
5688 assert_match!(RevocationStatus::NotAsFarAsWeKnow
5689 = cert.revocation_status(p, None));
5690
5691 assert_eq!(cert.user_attributes().count(), 1);
5692 let ua = cert.user_attributes().next().unwrap();
5693 if revoked {
5694 assert_match!(RevocationStatus::Revoked(_)
5695 = ua.revocation_status(p, t));
5696 } else {
5697 assert_match!(RevocationStatus::NotAsFarAsWeKnow
5698 = ua.revocation_status(p, t));
5699 }
5700 }
5701
5702 tracer!(true, "userid_revoked2", 0);
5703
5704 let p = &P::new();
5705 let tests : [(&str, Box<dyn Fn(&dyn Policy, &Cert, bool, _)>); 2] = [
5706 ("userid", Box::new(check_userids)),
5707 ("user-attribute", Box::new(check_uas)),
5708 ];
5709
5710 for (f, check) in tests.iter()
5711 {
5712 t!("Checking {} revocation", f);
5713
5714 t!("Normal key");
5715 let cert = Cert::from_bytes(
5716 crate::tests::key(
5717 &format!("really-revoked-{}-0-public.pgp", f))).unwrap();
5718
5719 let now = crate::now();
5720 let selfsig0
5721 = cert.userids().with_policy(p, now).map(|b| {
5722 b.binding_signature().signature_creation_time().unwrap()
5723 })
5724 .max().unwrap();
5725
5726 check(p, &cert, false, selfsig0);
5727 check(p, &cert, false, now);
5728
5729 // A soft-revocation.
5730 let cert = cert.merge_public_and_secret(
5731 Cert::from_bytes(
5732 crate::tests::key(
5733 &format!("really-revoked-{}-1-soft-revocation.pgp", f))
5734 ).unwrap()).unwrap();
5735
5736 check(p, &cert, false, selfsig0);
5737 check(p, &cert, true, now);
5738
5739 // A new self signature. This should override the soft-revocation.
5740 let cert = cert.merge_public_and_secret(
5741 Cert::from_bytes(
5742 crate::tests::key(
5743 &format!("really-revoked-{}-2-new-self-sig.pgp", f))
5744 ).unwrap()).unwrap();
5745
5746 check(p, &cert, false, selfsig0);
5747 check(p, &cert, false, now);
5748
5749 // A hard revocation. Unlike for Certs, this does NOT trump
5750 // everything.
5751 let cert = cert.merge_public_and_secret(
5752 Cert::from_bytes(
5753 crate::tests::key(
5754 &format!("really-revoked-{}-3-hard-revocation.pgp", f))
5755 ).unwrap()).unwrap();
5756
5757 check(p, &cert, false, selfsig0);
5758 check(p, &cert, true, now);
5759
5760 // A newer self signature.
5761 let cert = cert.merge_public_and_secret(
5762 Cert::from_bytes(
5763 crate::tests::key(
5764 &format!("really-revoked-{}-4-new-self-sig.pgp", f))
5765 ).unwrap()).unwrap();
5766
5767 check(p, &cert, false, selfsig0);
5768 check(p, &cert, false, now);
5769 }
5770 }
5771
5772 #[test]
5773 fn unrevoked() {
5774 let p = &P::new();
5775 let cert =
5776 Cert::from_bytes(crate::tests::key("un-revoked-userid.pgp")).unwrap();
5777
5778 for uid in cert.userids().with_policy(p, None) {
5779 assert_eq!(uid.revocation_status(), RevocationStatus::NotAsFarAsWeKnow);
5780 }
5781 }
5782
5783 #[test]
5784 fn is_tsk() {
5785 let cert = Cert::from_bytes(
5786 crate::tests::key("already-revoked.pgp")).unwrap();
5787 assert!(! cert.is_tsk());
5788
5789 let cert = Cert::from_bytes(
5790 crate::tests::key("already-revoked-private.pgp")).unwrap();
5791 assert!(cert.is_tsk());
5792 }
5793
5794 #[test]
5795 fn export_only_exports_public_key() {
5796 let cert = Cert::from_bytes(
5797 crate::tests::key("testy-new-private.pgp")).unwrap();
5798 assert!(cert.is_tsk());
5799
5800 let mut v = Vec::new();
5801 cert.serialize(&mut v).unwrap();
5802 let cert = Cert::from_bytes(&v).unwrap();
5803 assert!(! cert.is_tsk());
5804 }
5805
5806 // Make sure that when merging two Certs, the primary key and
5807 // subkeys with and without a private key are merged.
5808 #[test]
5809 fn public_private_merge() {
5810 let (tsk, _) = CertBuilder::general_purpose(Some("foo@example.com"))
5811 .generate().unwrap();
5812 // tsk is now a cert, but it still has its private bits.
5813 assert!(tsk.primary.key().has_secret());
5814 assert!(tsk.is_tsk());
5815 let subkey_count = tsk.subkeys().count();
5816 assert!(subkey_count > 0);
5817 assert!(tsk.subkeys().all(|k| k.key().has_secret()));
5818
5819 // This will write out the tsk as a cert, i.e., without any
5820 // private bits.
5821 let mut cert_bytes = Vec::new();
5822 tsk.serialize(&mut cert_bytes).unwrap();
5823
5824 // Reading it back in, the private bits have been stripped.
5825 let cert = Cert::from_bytes(&cert_bytes[..]).unwrap();
5826 assert!(! cert.primary.key().has_secret());
5827 assert!(!cert.is_tsk());
5828 assert!(cert.subkeys().all(|k| ! k.key().has_secret()));
5829
5830 let merge1 = cert.clone().merge_public_and_secret(tsk.clone()).unwrap();
5831 assert!(merge1.is_tsk());
5832 assert!(merge1.primary.key().has_secret());
5833 assert_eq!(merge1.subkeys().count(), subkey_count);
5834 assert!(merge1.subkeys().all(|k| k.key().has_secret()));
5835
5836 let merge2 = tsk.clone().merge_public_and_secret(cert.clone()).unwrap();
5837 assert!(merge2.is_tsk());
5838 assert!(merge2.primary.key().has_secret());
5839 assert_eq!(merge2.subkeys().count(), subkey_count);
5840 assert!(merge2.subkeys().all(|k| k.key().has_secret()));
5841 }
5842
5843 #[test]
5844 fn issue_120() {
5845 let cert = "
5846-----BEGIN PGP ARMORED FILE-----
5847
5848xcBNBFoVcvoBCACykTKOJddF8SSUAfCDHk86cNTaYnjCoy72rMgWJsrMLnz/V16B
5849J9M7l6nrQ0JMnH2Du02A3w+kNb5q97IZ/M6NkqOOl7uqjyRGPV+XKwt0G5mN/ovg
58508630BZAYS3QzavYf3tni9aikiGH+zTFX5pynTNfYRXNBof3Xfzl92yad2bIt4ITD
5851NfKPvHRko/tqWbclzzEn72gGVggt1/k/0dKhfsGzNogHxg4GIQ/jR/XcqbDFR3RC
5852/JJjnTOUPGsC1y82Xlu8udWBVn5mlDyxkad5laUpWWg17anvczEAyx4TTOVItLSu
585343iPdKHSs9vMXWYID0bg913VusZ2Ofv690nDABEBAAHNJFRlc3R5IE1jVGVzdGZh
5854Y2UgPHRlc3R5QGV4YW1wbGUub3JnPsLAlAQTAQgAPhYhBD6Id8h3J0aSl1GJ9dA/
5855b4ZSJv6LBQJaFXL6AhsDBQkDwmcABQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJ
5856ENA/b4ZSJv6Lxo8H/1XMt+Nqa6e0SG/up3ypKe5nplA0p/9j/s2EIsP8S8uPUd+c
5857WS17XOmPwkNDmHeL3J6hzwL74NlYSLEtyf7WoOV74xAKQA9WkqaKPHCtpll8aFWA
5858ktQDLWTPeKuUuSlobAoRtO17ZmheSQzmm7JYt4Ahkxt3agqGT05OsaAey6nIKqpq
5859ArokvdHTZ7AFZeSJIWmuCoT9M1lo3LAtLnRGOhBMJ5dDIeOwflJwNBXlJVi4mDPK
5860+fumV0MbSPvZd1/ivFjSpQyudWWtv1R1nAK7+a4CPTGxPvAQkLtRsL/V+Q7F3BJG
5861jAn4QVx8p4t3NOPuNgcoZpLBE3sc4Nfs5/CphMLHwE0EWhVy+gEIALSpjYD+tuWC
5862rj6FGP6crQjQzVlH+7axoM1ooTwiPs4fzzt2iLw3CJyDUviM5F9ZBQTei635RsAR
5863a/CJTSQYAEU5yXXxhoe0OtwnuvsBSvVT7Fox3pkfNTQmwMvkEbodhfKpqBbDKCL8
5864f5A8Bb7aISsLf0XRHWDkHVqlz8LnOR3f44wEWiTeIxLc8S1QtwX/ExyW47oPsjs9
5865ShCmwfSpcngH/vGBRTO7WeI54xcAtKSm/20B/MgrUl5qFo17kUWot2C6KjuZKkHk
58663WZmJwQz+6rTB11w4AXt8vKkptYQCkfat2FydGpgRO5dVg6aWNJefOJNkC7MmlzC
5867ZrrAK8FJ6jcAEQEAAcLAdgQYAQgAIBYhBD6Id8h3J0aSl1GJ9dA/b4ZSJv6LBQJa
5868FXL6AhsMAAoJENA/b4ZSJv6Lt7kH/jPr5wg8lcamuLj4lydYiLttvvTtDTlD1TL+
5869IfwVARB/ruoerlEDr0zX1t3DCEcvJDiZfOqJbXtHt70+7NzFXrYxfaNFmikMgSQT
5870XqHrMQho4qpseVOeJPWGzGOcrxCdw/ZgrWbkDlAU5KaIvk+M4wFPivjbtW2Ro2/F
5871J4I/ZHhJlIPmM+hUErHC103b08pBENXDQlXDma7LijH5kWhyfF2Ji7Ft0EjghBaW
5872AeGalQHjc5kAZu5R76Mwt06MEQ/HL1pIvufTFxkr/SzIv8Ih7Kexb0IrybmfD351
5873Pu1xwz57O4zo1VYf6TqHJzVC3OMvMUM2hhdecMUe5x6GorNaj6g=
5874=1Vzu
5875-----END PGP ARMORED FILE-----
5876";
5877 assert!(Cert::from_bytes(cert).is_err());
5878 }
5879
5880 #[test]
5881 fn missing_uids() {
5882 let (cert, _) = CertBuilder::new()
5883 .add_userid("test1@example.com")
5884 .add_userid("test2@example.com")
5885 .add_transport_encryption_subkey()
5886 .add_certification_subkey()
5887 .generate().unwrap();
5888 assert_eq!(cert.subkeys().count(), 2);
5889 let pile = cert
5890 .into_packet_pile()
5891 .into_children()
5892 .filter(|pkt| {
5893 match pkt {
5894 &Packet::PublicKey(_) | &Packet::PublicSubkey(_)
5895 | &Packet::SecretKey(_) | &Packet::SecretSubkey(_) => true,
5896 &Packet::Signature(ref sig) => {
5897 sig.typ() == SignatureType::DirectKey
5898 || sig.typ() == SignatureType::SubkeyBinding
5899 }
5900 e => {
5901 eprintln!("{:?}", e);
5902 false
5903 }
5904 }
5905 })
5906 .collect::<Vec<_>>();
5907 eprintln!("parse back");
5908 let cert = Cert::try_from(pile).unwrap();
5909
5910 assert_eq!(cert.subkeys().count(), 2);
5911 }
5912
5913 #[test]
5914 fn signature_order() {
5915 let p = &P::new();
5916 let neal = Cert::from_bytes(crate::tests::key("neal.pgp")).unwrap();
5917
5918 // This test is useless if we don't have some lists with more
5919 // than one signature.
5920 let mut cmps = 0;
5921
5922 for uid in neal.userids() {
5923 for sigs in [
5924 uid.self_signatures().collect::<Vec<_>>(),
5925 uid.certifications().collect::<Vec<_>>(),
5926 uid.self_revocations().collect::<Vec<_>>(),
5927 uid.other_revocations().collect::<Vec<_>>()
5928 ].iter() {
5929 for sigs in sigs.windows(2) {
5930 cmps += 1;
5931 assert!(sigs[0].signature_creation_time()
5932 >= sigs[1].signature_creation_time());
5933 }
5934 }
5935
5936 // Make sure we return the most recent first.
5937 assert_eq!(uid.self_signatures().next().unwrap(),
5938 uid.binding_signature(p, None).unwrap());
5939 }
5940
5941 assert!(cmps > 0);
5942 }
5943
5944 #[test]
5945 fn cert_reject_keyrings() {
5946 let mut keyring = Vec::new();
5947 keyring.extend_from_slice(crate::tests::key("neal.pgp"));
5948 keyring.extend_from_slice(crate::tests::key("neal.pgp"));
5949 assert!(Cert::from_bytes(&keyring).is_err());
5950 }
5951
5952 #[test]
5953 fn primary_userid() {
5954 // 'really-revoked-userid' has two user ids. One of them is
5955 // revoked and then restored. Neither of the user ids has the
5956 // primary userid bit set.
5957 //
5958 // This test makes sure that Cert::primary_userid prefers
5959 // unrevoked user ids to revoked user ids, even if the latter
5960 // have newer self signatures.
5961
5962 let p = &P::new();
5963 let cert = Cert::from_bytes(
5964 crate::tests::key("really-revoked-userid-0-public.pgp")).unwrap();
5965
5966 let now = crate::now();
5967 let selfsig0
5968 = cert.userids().with_policy(p, now).map(|b| {
5969 b.binding_signature().signature_creation_time().unwrap()
5970 })
5971 .max().unwrap();
5972
5973 // The self-sig for:
5974 //
5975 // Slim Shady: 2019-09-14T14:21
5976 // Eminem: 2019-09-14T14:22
5977 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
5978 .primary_userid().unwrap().userid().value(),
5979 b"Eminem");
5980 assert_eq!(cert.with_policy(p, now).unwrap()
5981 .primary_userid().unwrap().userid().value(),
5982 b"Eminem");
5983
5984 // A soft-revocation for "Slim Shady".
5985 let cert = cert.merge_public_and_secret(
5986 Cert::from_bytes(
5987 crate::tests::key("really-revoked-userid-1-soft-revocation.pgp")
5988 ).unwrap()).unwrap();
5989
5990 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
5991 .primary_userid().unwrap().userid().value(),
5992 b"Eminem");
5993 assert_eq!(cert.with_policy(p, now).unwrap()
5994 .primary_userid().unwrap().userid().value(),
5995 b"Eminem");
5996
5997 // A new self signature for "Slim Shady". This should
5998 // override the soft-revocation.
5999 let cert = cert.merge_public_and_secret(
6000 Cert::from_bytes(
6001 crate::tests::key("really-revoked-userid-2-new-self-sig.pgp")
6002 ).unwrap()).unwrap();
6003
6004 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6005 .primary_userid().unwrap().userid().value(),
6006 b"Eminem");
6007 assert_eq!(cert.with_policy(p, now).unwrap()
6008 .primary_userid().unwrap().userid().value(),
6009 b"Slim Shady");
6010
6011 // A hard revocation for "Slim Shady".
6012 let cert = cert.merge_public_and_secret(
6013 Cert::from_bytes(
6014 crate::tests::key("really-revoked-userid-3-hard-revocation.pgp")
6015 ).unwrap()).unwrap();
6016
6017 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6018 .primary_userid().unwrap().userid().value(),
6019 b"Eminem");
6020 assert_eq!(cert.with_policy(p, now).unwrap()
6021 .primary_userid().unwrap().userid().value(),
6022 b"Eminem");
6023
6024 // A newer self signature for "Slim Shady". Unlike for Certs, this
6025 // does NOT trump everything.
6026 let cert = cert.merge_public_and_secret(
6027 Cert::from_bytes(
6028 crate::tests::key("really-revoked-userid-4-new-self-sig.pgp")
6029 ).unwrap()).unwrap();
6030
6031 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6032 .primary_userid().unwrap().userid().value(),
6033 b"Eminem");
6034 assert_eq!(cert.with_policy(p, now).unwrap()
6035 .primary_userid().unwrap().userid().value(),
6036 b"Slim Shady");
6037
6038 // Play with the primary user id flag.
6039
6040 let cert = Cert::from_bytes(
6041 crate::tests::key("primary-key-0-public.pgp")).unwrap();
6042 let selfsig0
6043 = cert.userids().with_policy(p, now).map(|b| {
6044 b.binding_signature().signature_creation_time().unwrap()
6045 })
6046 .max().unwrap();
6047
6048 // There is only a single User ID.
6049 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6050 .primary_userid().unwrap().userid().value(),
6051 b"aaaaa");
6052 assert_eq!(cert.with_policy(p, now).unwrap()
6053 .primary_userid().unwrap().userid().value(),
6054 b"aaaaa");
6055
6056
6057 // Add a second user id. Since neither is marked primary, the
6058 // newer one should be considered primary.
6059 let cert = cert.merge_public_and_secret(
6060 Cert::from_bytes(
6061 crate::tests::key("primary-key-1-add-userid-bbbbb.pgp")
6062 ).unwrap()).unwrap();
6063
6064 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6065 .primary_userid().unwrap().userid().value(),
6066 b"aaaaa");
6067 assert_eq!(cert.with_policy(p, now).unwrap()
6068 .primary_userid().unwrap().userid().value(),
6069 b"bbbbb");
6070
6071 // Mark aaaaa as primary. It is now primary and the newest one.
6072 let cert = cert.merge_public_and_secret(
6073 Cert::from_bytes(
6074 crate::tests::key("primary-key-2-make-aaaaa-primary.pgp")
6075 ).unwrap()).unwrap();
6076
6077 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6078 .primary_userid().unwrap().userid().value(),
6079 b"aaaaa");
6080 assert_eq!(cert.with_policy(p, now).unwrap()
6081 .primary_userid().unwrap().userid().value(),
6082 b"aaaaa");
6083
6084 // Update the preferences on bbbbb. It is now the newest, but
6085 // it is not marked as primary.
6086 let cert = cert.merge_public_and_secret(
6087 Cert::from_bytes(
6088 crate::tests::key("primary-key-3-make-bbbbb-new-self-sig.pgp")
6089 ).unwrap()).unwrap();
6090
6091 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6092 .primary_userid().unwrap().userid().value(),
6093 b"aaaaa");
6094 assert_eq!(cert.with_policy(p, now).unwrap()
6095 .primary_userid().unwrap().userid().value(),
6096 b"aaaaa");
6097
6098 // Mark bbbbb as primary. It is now the newest and marked as
6099 // primary.
6100 let cert = cert.merge_public_and_secret(
6101 Cert::from_bytes(
6102 crate::tests::key("primary-key-4-make-bbbbb-primary.pgp")
6103 ).unwrap()).unwrap();
6104
6105 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6106 .primary_userid().unwrap().userid().value(),
6107 b"aaaaa");
6108 assert_eq!(cert.with_policy(p, now).unwrap()
6109 .primary_userid().unwrap().userid().value(),
6110 b"bbbbb");
6111
6112 // Update the preferences on aaaaa. It is now has the newest
6113 // self sig, but that self sig does not say that it is
6114 // primary.
6115 let cert = cert.merge_public_and_secret(
6116 Cert::from_bytes(
6117 crate::tests::key("primary-key-5-make-aaaaa-self-sig.pgp")
6118 ).unwrap()).unwrap();
6119
6120 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6121 .primary_userid().unwrap().userid().value(),
6122 b"aaaaa");
6123 assert_eq!(cert.with_policy(p, now).unwrap()
6124 .primary_userid().unwrap().userid().value(),
6125 b"bbbbb");
6126
6127 // Hard revoke aaaaa. Unlike with Certs, a hard revocation is
6128 // not treated specially.
6129 let cert = cert.merge_public_and_secret(
6130 Cert::from_bytes(
6131 crate::tests::key("primary-key-6-revoked-aaaaa.pgp")
6132 ).unwrap()).unwrap();
6133
6134 assert_eq!(cert.with_policy(p, selfsig0).unwrap()
6135 .primary_userid().unwrap().userid().value(),
6136 b"aaaaa");
6137 assert_eq!(cert.with_policy(p, now).unwrap()
6138 .primary_userid().unwrap().userid().value(),
6139 b"bbbbb");
6140 }
6141
6142 #[test]
6143 fn binding_signature_lookup() {
6144 // Check that searching for the right binding signature works
6145 // even when there are signatures with the same time.
6146
6147 use crate::types::Features;
6148 use crate::packet::key::Key6;
6149
6150 let p = &P::new();
6151
6152 let a_sec = time::Duration::new(1, 0);
6153 let time_zero = time::UNIX_EPOCH;
6154
6155 let t1 = time::UNIX_EPOCH + time::Duration::new(946681200, 0); // 2000-1-1
6156 let t2 = time::UNIX_EPOCH + time::Duration::new(978303600, 0); // 2001-1-1
6157 let t3 = time::UNIX_EPOCH + time::Duration::new(1009839600, 0); // 2002-1-1
6158 let t4 = time::UNIX_EPOCH + time::Duration::new(1041375600, 0); // 2003-1-1
6159
6160 let mut key: key::SecretKey
6161 = Key6::generate_ecc(true, Curve::Ed25519).unwrap().into();
6162 key.set_creation_time(t1).unwrap();
6163 let mut pair = key.clone().into_keypair().unwrap();
6164 let pk : key::PublicKey = key.clone().into();
6165 let mut cert = Cert::try_from(vec![
6166 pk.into(),
6167 ]).unwrap();
6168 let uid: UserID = "foo@example.org".into();
6169 let sig = uid.certify(&mut pair, &cert,
6170 SignatureType::PositiveCertification,
6171 None,
6172 t1).unwrap();
6173 cert = cert.insert_packets(
6174 vec![Packet::from(uid), sig.into()]).unwrap().0;
6175
6176 const N: usize = 5;
6177 for (t, offset) in &[ (t2, 0), (t4, 0), (t3, 1 * N), (t1, 3 * N) ] {
6178 for i in 0..N {
6179 let binding = signature::SignatureBuilder::new(SignatureType::DirectKey)
6180 .set_features(Features::sequoia()).unwrap()
6181 .set_key_flags(KeyFlags::empty()).unwrap()
6182 .set_signature_creation_time(t1).unwrap()
6183 // Vary this...
6184 .set_key_validity_period(Some(
6185 time::Duration::new((1 + i as u64) * 24 * 60 * 60, 0)))
6186 .unwrap()
6187 .set_preferred_hash_algorithms(vec![HashAlgorithm::SHA512]).unwrap()
6188 .set_signature_creation_time(*t).unwrap()
6189 .sign_direct_key(&mut pair, key.parts_as_public()).unwrap();
6190
6191 let binding : Packet = binding.into();
6192
6193 cert = cert.insert_packets(binding).unwrap().0;
6194 // A time that matches multiple signatures.
6195 let direct_signatures =
6196 cert.primary_key().bundle().self_signatures()
6197 .collect::<Vec<_>>();
6198 assert_eq!(cert.primary_key().with_policy(p, *t).unwrap()
6199 .direct_key_signature().ok(),
6200 direct_signatures.get(*offset).cloned());
6201 // A time that doesn't match any signature.
6202 assert_eq!(cert.primary_key().with_policy(p, *t + a_sec).unwrap()
6203 .direct_key_signature().ok(),
6204 direct_signatures.get(*offset).cloned());
6205
6206 // The current time, which should use the first signature.
6207 assert_eq!(cert.primary_key().with_policy(p, None).unwrap()
6208 .direct_key_signature().ok(),
6209 direct_signatures.get(0).cloned());
6210
6211 // The beginning of time, which should return no
6212 // binding signatures.
6213 assert!(cert.primary_key().with_policy(p, time_zero).is_err());
6214 }
6215 }
6216 }
6217
6218 #[test]
6219 fn keysigning_party() {
6220 use crate::packet::signature;
6221
6222 for cs in &[ CipherSuite::Cv25519,
6223 CipherSuite::P256,
6224 CipherSuite::P384,
6225 CipherSuite::P521,
6226 CipherSuite::RSA2k ]
6227 {
6228 if cs.is_supported().is_err() {
6229 eprintln!("Skipping {:?} because it is not supported.", cs);
6230 continue;
6231 }
6232
6233 let (alice, _) = CertBuilder::new()
6234 .set_cipher_suite(*cs)
6235 .add_userid("alice@foo.com")
6236 .generate().unwrap();
6237
6238 let (bob, _) = CertBuilder::new()
6239 .set_cipher_suite(*cs)
6240 .add_userid("bob@bar.com")
6241 .add_signing_subkey()
6242 .generate().unwrap();
6243
6244 assert_eq!(bob.userids().len(), 1);
6245 let bob_userid_binding = bob.userids().next().unwrap();
6246 assert_eq!(bob_userid_binding.userid().value(), b"bob@bar.com");
6247
6248 let sig_template
6249 = signature::SignatureBuilder::new(SignatureType::GenericCertification)
6250 .set_trust_signature(255, 120)
6251 .unwrap();
6252
6253 // Have alice certify the binding "bob@bar.com" and bob's key.
6254 let alice_certifies_bob
6255 = bob_userid_binding.userid().bind(
6256 &mut alice.primary_key().key().clone().parts_into_secret()
6257 .unwrap().into_keypair().unwrap(),
6258 &bob,
6259 sig_template).unwrap();
6260
6261 let bob = bob.insert_packets(alice_certifies_bob.clone()).unwrap().0;
6262
6263 // Make sure the certification is merged, and put in the right
6264 // place.
6265 assert_eq!(bob.userids().len(), 1);
6266 let bob_userid_binding = bob.userids().next().unwrap();
6267 assert_eq!(bob_userid_binding.userid().value(), b"bob@bar.com");
6268
6269 // Canonicalizing Bob's cert without having Alice's key
6270 // has to resort to a heuristic to order third party
6271 // signatures. However, since we know the signature's
6272 // type (GenericCertification), we know that it can only
6273 // go to the only userid, so there is no ambiguity in this
6274 // case.
6275 assert_eq!(bob_userid_binding.certifications().collect::<Vec<_>>(),
6276 vec![&alice_certifies_bob]);
6277
6278 // Make sure the certification is correct.
6279 alice_certifies_bob
6280 .verify_userid_binding(alice.primary_key().key(),
6281 bob.primary_key().key(),
6282 bob_userid_binding.userid()).unwrap();
6283 }
6284 }
6285
6286 #[test]
6287 fn decrypt_encrypt_secrets() -> Result<()> {
6288 let p: crate::crypto::Password = "streng geheim".into();
6289 let (mut cert, _) = CertBuilder::new()
6290 .add_transport_encryption_subkey()
6291 .set_password(Some(p.clone()))
6292 .generate()?;
6293 assert_eq!(cert.keys().secret().count(), 2);
6294 assert_eq!(cert.keys().unencrypted_secret().count(), 0);
6295
6296 for (i, ka) in cert.clone().keys().secret().enumerate() {
6297 let key = ka.key().clone().decrypt_secret(&p)?;
6298 cert = if i == 0 {
6299 cert.insert_packets(key.role_into_primary())?.0
6300 } else {
6301 cert.insert_packets(key.role_into_subordinate())?.0
6302 };
6303 assert_eq!(cert.keys().secret().count(), 2);
6304 assert_eq!(cert.keys().unencrypted_secret().count(), i + 1);
6305 }
6306
6307 assert_eq!(cert.keys().secret().count(), 2);
6308 assert_eq!(cert.keys().unencrypted_secret().count(), 2);
6309
6310 for (i, ka) in cert.clone().keys().secret().enumerate() {
6311 let key = ka.key().clone().encrypt_secret(&p)?;
6312 cert = if i == 0 {
6313 cert.insert_packets(key.role_into_primary())?.0
6314 } else {
6315 cert.insert_packets(key.role_into_subordinate())?.0
6316 };
6317 assert_eq!(cert.keys().secret().count(), 2);
6318 assert_eq!(cert.keys().unencrypted_secret().count(), 2 - 1 - i);
6319 }
6320
6321 assert_eq!(cert.keys().secret().count(), 2);
6322 assert_eq!(cert.keys().unencrypted_secret().count(), 0);
6323 Ok(())
6324 }
6325
6326 /// Tests that Cert:.into_packets() and Cert::serialize(..) agree.
6327 #[test]
6328 fn test_into_packets() -> Result<()> {
6329 use crate::serialize::SerializeInto;
6330
6331 let dkg = Cert::from_bytes(crate::tests::key("dkg.pgp"))?;
6332 let mut buf = Vec::new();
6333 for p in dkg.clone().into_packets() {
6334 p.serialize(&mut buf)?;
6335 }
6336 let dkg = dkg.to_vec()?;
6337 if false && buf != dkg {
6338 std::fs::write("/tmp/buf", &buf)?;
6339 std::fs::write("/tmp/dkg", &dkg)?;
6340 }
6341 assert_eq!(buf, dkg);
6342 Ok(())
6343 }
6344
6345 #[test]
6346 fn test_canonicalization() -> Result<()> {
6347 let p = crate::policy::StandardPolicy::new();
6348
6349 let primary: Key<_, key::PrimaryRole> =
6350 key::Key6::generate_ecc(true, Curve::Ed25519)?.into();
6351 let cert = Cert::try_from(vec![primary.into()])?;
6352
6353 // We now add components without binding signatures. They
6354 // should be kept, be enumerable, but ignored if a policy is
6355 // applied.
6356
6357 // Add a bare userid.
6358 let uid = UserID::from("foo@example.org");
6359 let cert = cert.insert_packets(uid)?.0;
6360 assert_eq!(cert.userids().count(), 1);
6361 assert_eq!(cert.userids().with_policy(&p, None).count(), 0);
6362
6363 // Add a bare user attribute.
6364 use packet::user_attribute::{Subpacket, Image};
6365 let ua = UserAttribute::new(&[
6366 Subpacket::Image(
6367 Image::Private(100, vec![0, 1, 2].into_boxed_slice())),
6368 ])?;
6369 let cert = cert.insert_packets(ua)?.0;
6370 assert_eq!(cert.user_attributes().count(), 1);
6371 assert_eq!(cert.user_attributes().with_policy(&p, None).count(), 0);
6372
6373 // Add a bare signing subkey.
6374 let signing_subkey: Key<_, key::SubordinateRole> =
6375 key::Key6::generate_ecc(true, Curve::Ed25519)?.into();
6376 let _signing_subkey_pair = signing_subkey.clone().into_keypair()?;
6377 let cert = cert.insert_packets(signing_subkey)?.0;
6378 assert_eq!(cert.keys().subkeys().count(), 1);
6379 assert_eq!(cert.keys().subkeys().with_policy(&p, None).count(), 0);
6380
6381 // Add a component that Sequoia doesn't understand.
6382 let mut fake_key = packet::Unknown::new(
6383 packet::Tag::PublicSubkey, anyhow::anyhow!("fake key"));
6384 fake_key.set_body("fake key".into());
6385 let cert = cert.insert_packets(vec![Packet::from(fake_key)])?.0;
6386 assert_eq!(cert.unknowns().count(), 1);
6387 assert_eq!(cert.unknowns().next().unwrap().unknown().tag(),
6388 packet::Tag::PublicSubkey);
6389
6390 Ok(())
6391 }
6392
6393 #[test]
6394 #[allow(deprecated)]
6395 fn canonicalize_with_v3_sig() -> Result<()> {
6396 skip_unless_supported!(crate::types::PublicKeyAlgorithm::DSA);
6397
6398 // This test relies on being able to validate SHA-1
6399 // signatures. The standard policy rejects SHA-1. So, use a
6400 // custom policy.
6401 let p = &P::new();
6402 let sha1 =
6403 p.hash_cutoff(
6404 HashAlgorithm::SHA1, HashAlgoSecurity::CollisionResistance)
6405 .unwrap();
6406 let p = &P::at(sha1 - std::time::Duration::from_secs(1));
6407
6408 let cert = Cert::from_bytes(
6409 crate::tests::key("eike-v3-v4.pgp"))?;
6410 dbg!(&cert);
6411 assert_eq!(cert.userids()
6412 .with_policy(p, None)
6413 .count(), 1);
6414 Ok(())
6415 }
6416
6417 /// Asserts that key expiration times on direct key signatures are
6418 /// honored.
6419 #[test]
6420 fn issue_215() {
6421 let p = &P::new();
6422 let cert = Cert::from_bytes(crate::tests::key(
6423 "issue-215-expiration-on-direct-key-sig.pgp")).unwrap();
6424 assert_match!(
6425 Error::Expired(_)
6426 = cert.with_policy(p, None).unwrap().alive()
6427 .unwrap_err().downcast().unwrap());
6428 assert_match!(
6429 Error::Expired(_)
6430 = cert.primary_key().with_policy(p, None).unwrap()
6431 .alive().unwrap_err().downcast().unwrap());
6432 }
6433
6434 /// Tests that secrets are kept when merging.
6435 #[test]
6436 fn merge_keeps_secrets() -> Result<()> {
6437 let (cert_s, _) =
6438 CertBuilder::general_purpose(Some("uid")).generate()?;
6439 let cert_p = cert_s.clone().strip_secret_key_material();
6440
6441 // Merge key into cert.
6442 let cert = cert_p.clone().merge_public_and_secret(cert_s.clone())?;
6443 assert!(cert.keys().all(|ka| ka.has_secret()));
6444
6445 // Merge cert into key.
6446 let cert = cert_s.clone().merge_public_and_secret(cert_p.clone())?;
6447 assert!(cert.keys().all(|ka| ka.has_secret()));
6448
6449 Ok(())
6450 }
6451
6452 /// Tests that secrets that are merged in are preferred to
6453 /// existing secrets.
6454 #[test]
6455 fn merge_prefers_merged_in_secrets() -> Result<()> {
6456 let pw: crate::crypto::Password = "foo".into();
6457 let (cert_encrypted_secrets, _) =
6458 CertBuilder::general_purpose(Some("uid"))
6459 .set_password(Some(pw.clone()))
6460 .generate()?;
6461
6462 let mut cert_plain_secrets = cert_encrypted_secrets.clone();
6463 for ka in cert_encrypted_secrets.keys().secret() {
6464 assert!(! ka.key().has_unencrypted_secret());
6465 let key = ka.key().clone().decrypt_secret(&pw)?;
6466 assert!(key.has_unencrypted_secret());
6467
6468 let key: Packet = if ka.primary() {
6469 key.role_into_primary().into()
6470 } else {
6471 key.role_into_subordinate().into()
6472 };
6473
6474 cert_plain_secrets =
6475 cert_plain_secrets.insert_packets(vec![key])?.0;
6476 }
6477 assert!(
6478 cert_plain_secrets.keys().all(|ka| ka.key().has_unencrypted_secret()));
6479
6480 // Merge unencrypted secrets into encrypted secrets.
6481 let cert = cert_encrypted_secrets.clone().merge_public_and_secret(
6482 cert_plain_secrets.clone())?;
6483 assert!(cert.keys().all(|ka| ka.key().has_unencrypted_secret()));
6484
6485 // Merge encrypted secrets into unencrypted secrets.
6486 let cert = cert_plain_secrets.clone().merge_public_and_secret(
6487 cert_encrypted_secrets.clone())?;
6488 assert!(cert.keys().all(|ka| ka.has_secret()
6489 && ! ka.key().has_unencrypted_secret()));
6490
6491 Ok(())
6492 }
6493
6494 /// Tests that secrets are kept when canonicalizing.
6495 #[test]
6496 fn canonicalizing_keeps_secrets() -> Result<()> {
6497 let primary: Key<_, key::PrimaryRole> =
6498 key::Key6::generate_ecc(true, Curve::Ed25519)?.into();
6499 let mut primary_pair = primary.clone().into_keypair()?;
6500 let cert = Cert::try_from(vec![primary.clone().into()])?;
6501
6502 let subkey_sec: Key<_, key::SubordinateRole> =
6503 key::Key6::generate_ecc(false, Curve::Cv25519)?.into();
6504 let subkey_pub = subkey_sec.clone().take_secret().0;
6505 let builder = signature::SignatureBuilder::new(SignatureType::SubkeyBinding)
6506 .set_key_flags(KeyFlags::empty()
6507 .set_transport_encryption())?;
6508 let binding = subkey_sec.bind(&mut primary_pair, &cert, builder)?;
6509
6510 let cert = Cert::try_from(vec![
6511 primary.clone().into(),
6512 subkey_pub.clone().into(),
6513 binding.clone().into(),
6514 subkey_sec.clone().into(),
6515 binding.clone().into(),
6516 ])?;
6517 assert_eq!(cert.keys().subkeys().count(), 1);
6518 assert_eq!(cert.keys().unencrypted_secret().subkeys().count(), 1);
6519
6520 let cert = Cert::try_from(vec![
6521 primary.clone().into(),
6522 subkey_sec.clone().into(),
6523 binding.clone().into(),
6524 subkey_pub.clone().into(),
6525 binding.clone().into(),
6526 ])?;
6527 assert_eq!(cert.keys().subkeys().count(), 1);
6528 assert_eq!(cert.keys().unencrypted_secret().subkeys().count(), 1);
6529 Ok(())
6530 }
6531
6532 /// Demonstrates that subkeys are kept if a userid is later added
6533 /// without any keyflags.
6534 #[test]
6535 fn issue_361() -> Result<()> {
6536 let (cert, _) = CertBuilder::new()
6537 .add_transport_encryption_subkey()
6538 .generate()?;
6539 let p = &P::new();
6540 let cert_at = cert.with_policy(p,
6541 cert.primary_key().key().creation_time()
6542 + time::Duration::new(300, 0))
6543 .unwrap();
6544 assert_eq!(cert_at.userids().count(), 0);
6545 assert_eq!(cert_at.keys().count(), 2);
6546
6547 let mut primary_pair = cert.primary_key().key().clone()
6548 .parts_into_secret()?.into_keypair()?;
6549 let uid: UserID = "foo@example.org".into();
6550 let sig = uid.bind(
6551 &mut primary_pair, &cert,
6552 signature::SignatureBuilder::new(SignatureType::PositiveCertification))?;
6553 let cert = cert.insert_packets(vec![
6554 Packet::from(uid),
6555 sig.into(),
6556 ])?.0;
6557
6558 let cert_at = cert.with_policy(p,
6559 cert.primary_key().key().creation_time()
6560 + time::Duration::new(300, 0))
6561 .unwrap();
6562 assert_eq!(cert_at.userids().count(), 1);
6563 assert_eq!(cert_at.keys().count(), 2);
6564 Ok(())
6565 }
6566
6567 /// Demonstrates that binding signatures are considered valid even
6568 /// if the primary key is not marked as certification-capable.
6569 #[test]
6570 fn issue_321() -> Result<()> {
6571 let cert = Cert::from_bytes(
6572 crate::tests::file("contrib/pep/pEpkey-netpgp.asc"))?;
6573 assert_eq!(cert.userids().count(), 1);
6574 assert_eq!(cert.keys().count(), 1);
6575
6576 let mut p = P::new();
6577 p.accept_hash(HashAlgorithm::SHA1);
6578 let cert_at = cert.with_policy(&p, cert.primary_key().key().creation_time())
6579 .unwrap();
6580 assert_eq!(cert_at.userids().count(), 1);
6581 assert_eq!(cert_at.keys().count(), 1);
6582 Ok(())
6583 }
6584
6585 #[test]
6586 fn policy_uri_some() -> Result<()> {
6587 use crate::packet::prelude::SignatureBuilder;
6588 use crate::policy::StandardPolicy;
6589
6590 let p = &StandardPolicy::new();
6591
6592 let (alice, _) = CertBuilder::new().add_userid("Alice").generate()?;
6593
6594 let sig = SignatureBuilder::from(
6595 alice
6596 .with_policy(p, None)?
6597 .direct_key_signature().expect("Direct key signature")
6598 .clone()
6599 )
6600 .set_policy_uri("https://example.org/~alice/signing-policy.txt")?;
6601 assert_eq!(sig.policy_uri(), Some("https://example.org/~alice/signing-policy.txt".as_bytes()));
6602 Ok(())
6603 }
6604
6605 #[test]
6606 fn policy_uri_none() -> Result<()> {
6607 use crate::packet::prelude::SignatureBuilder;
6608 use crate::policy::StandardPolicy;
6609
6610 let p = &StandardPolicy::new();
6611
6612 let (alice, _) = CertBuilder::new().add_userid("Alice").generate()?;
6613
6614 let sig = SignatureBuilder::from(
6615 alice
6616 .with_policy(p, None)?
6617 .direct_key_signature().expect("Direct key signature")
6618 .clone()
6619 );
6620 assert_eq!(sig.policy_uri(), None);
6621 Ok(())
6622 }
6623
6624 #[test]
6625 #[allow(deprecated)]
6626 fn different_preferences() -> Result<()> {
6627 use crate::cert::Preferences;
6628 let p = &crate::policy::StandardPolicy::new();
6629
6630 // This key returns different preferences depending on how you
6631 // address it. (It has two user ids and the user ids have
6632 // different preference packets on their respective self
6633 // signatures.)
6634
6635 let cert = Cert::from_bytes(
6636 crate::tests::key("different-preferences.asc"))?;
6637 assert_eq!(cert.userids().count(), 2);
6638
6639 if let Some(userid) = cert.userids().next() {
6640 assert_eq!(userid.userid().value(),
6641 &b"Alice Confusion <alice@example.com>"[..]);
6642
6643 let userid = userid.with_policy(p, None).expect("valid");
6644
6645 use crate::types::SymmetricAlgorithm::*;
6646 assert_eq!(userid.preferred_symmetric_algorithms(),
6647 Some(&[ AES256, AES192, AES128, TripleDES ][..]));
6648
6649 use crate::types::HashAlgorithm::*;
6650 assert_eq!(userid.preferred_hash_algorithms(),
6651 Some(&[ SHA512, SHA384, SHA256, SHA224, SHA1 ][..]));
6652
6653 use crate::types::CompressionAlgorithm::*;
6654 assert_eq!(userid.preferred_compression_algorithms(),
6655 Some(&[ Zlib, BZip2, Zip ][..]));
6656
6657 assert_eq!(userid.preferred_aead_ciphersuites(), None);
6658
6659 // assert_eq!(userid.key_server_preferences(),
6660 // Some(KeyServerPreferences::new(&[])));
6661
6662 assert_eq!(userid.features(),
6663 Some(Features::new(&[]).set_seipdv1()));
6664 } else {
6665 panic!("two user ids");
6666 }
6667
6668 if let Some(userid) = cert.userids().next() {
6669 assert_eq!(userid.userid().value(),
6670 &b"Alice Confusion <alice@example.com>"[..]);
6671
6672 let userid = userid.with_policy(p, None).expect("valid");
6673
6674 use crate::types::SymmetricAlgorithm::*;
6675 assert_eq!(userid.preferred_symmetric_algorithms(),
6676 Some(&[ AES256, AES192, AES128, TripleDES ][..]));
6677
6678 use crate::types::HashAlgorithm::*;
6679 assert_eq!(userid.preferred_hash_algorithms(),
6680 Some(&[ SHA512, SHA384, SHA256, SHA224, SHA1 ][..]));
6681
6682 use crate::types::CompressionAlgorithm::*;
6683 assert_eq!(userid.preferred_compression_algorithms(),
6684 Some(&[ Zlib, BZip2, Zip ][..]));
6685
6686 assert_eq!(userid.preferred_aead_ciphersuites(), None);
6687
6688 assert_eq!(userid.key_server_preferences(),
6689 Some(KeyServerPreferences::new(&[0x80])));
6690
6691 assert_eq!(userid.features(),
6692 Some(Features::new(&[]).set_seipdv1()));
6693
6694 // Using the certificate should choose the primary user
6695 // id, which is this one (because it is lexicographically
6696 // earlier).
6697 let cert = cert.with_policy(p, None).expect("valid");
6698 assert_eq!(userid.preferred_symmetric_algorithms(),
6699 cert.preferred_symmetric_algorithms());
6700 assert_eq!(userid.preferred_hash_algorithms(),
6701 cert.preferred_hash_algorithms());
6702 assert_eq!(userid.preferred_compression_algorithms(),
6703 cert.preferred_compression_algorithms());
6704 assert_eq!(userid.preferred_aead_ciphersuites(),
6705 cert.preferred_aead_ciphersuites());
6706 assert_eq!(userid.key_server_preferences(),
6707 cert.key_server_preferences());
6708 assert_eq!(userid.features(),
6709 cert.features());
6710 } else {
6711 panic!("two user ids");
6712 }
6713
6714 if let Some(userid) = cert.userids().nth(1) {
6715 assert_eq!(userid.userid().value(),
6716 &b"Alice Confusion <alice@example.net>"[..]);
6717
6718 let userid = userid.with_policy(p, None).expect("valid");
6719
6720 use crate::types::SymmetricAlgorithm::*;
6721 assert_eq!(userid.preferred_symmetric_algorithms(),
6722 Some(&[ AES192, AES256, AES128, TripleDES ][..]));
6723
6724 use crate::types::HashAlgorithm::*;
6725 assert_eq!(userid.preferred_hash_algorithms(),
6726 Some(&[ SHA384, SHA512, SHA256, SHA224, SHA1 ][..]));
6727
6728 use crate::types::CompressionAlgorithm::*;
6729 assert_eq!(userid.preferred_compression_algorithms(),
6730 Some(&[ BZip2, Zlib, Zip ][..]));
6731
6732 assert_eq!(userid.preferred_aead_ciphersuites(), None);
6733
6734 assert_eq!(userid.key_server_preferences(),
6735 Some(KeyServerPreferences::new(&[0x80])));
6736
6737 assert_eq!(userid.features(),
6738 Some(Features::new(&[]).set_seipdv1()));
6739 } else {
6740 panic!("two user ids");
6741 }
6742
6743 Ok(())
6744 }
6745
6746 #[test]
6747 fn unsigned_components() -> Result<()> {
6748 // We have a certificate with an unsigned User ID, User
6749 // Attribute, encryption-capable subkey, and signing-capable
6750 // subkey. (Actually, they are signed, but the signatures are
6751 // bad.) We expect that when we parse such a certificate the
6752 // unsigned components are not dropped and they appear when
6753 // iterating over the components using, e.g., Cert::userids,
6754 // but not when we check for valid components.
6755
6756 let p = &crate::policy::StandardPolicy::new();
6757
6758 let cert = Cert::from_bytes(
6759 crate::tests::key("certificate-with-unsigned-components.asc"))?;
6760
6761 assert_eq!(cert.userids().count(), 2);
6762 assert_eq!(cert.userids().with_policy(p, None).count(), 1);
6763
6764 assert_eq!(cert.user_attributes().count(), 2);
6765 assert_eq!(cert.user_attributes().with_policy(p, None).count(), 1);
6766
6767 assert_eq!(cert.keys().count(), 1 + 4);
6768 assert_eq!(cert.keys().with_policy(p, None).count(), 1 + 2);
6769 Ok(())
6770 }
6771
6772 #[test]
6773 fn issue_504() -> Result<()> {
6774 let mut keyring = crate::tests::key("testy.pgp").to_vec();
6775 keyring.extend_from_slice(crate::tests::key("testy-new.pgp"));
6776
6777 // TryFrom<PacketPile>
6778 let pp = PacketPile::from_bytes(&keyring)?;
6779 assert!(matches!(
6780 Cert::try_from(pp.clone()).unwrap_err().downcast().unwrap(),
6781 Error::MalformedCert(_)
6782 ));
6783
6784 // Cert::TryFrom<Vec<Packet>>
6785 let v: Vec<Packet> = pp.into();
6786 assert!(matches!(
6787 Cert::try_from(v.clone()).unwrap_err().downcast().unwrap(),
6788 Error::MalformedCert(_)
6789 ));
6790
6791 // Cert::from_packet
6792 assert!(matches!(
6793 Cert::from_packets(v.into_iter()).unwrap_err().downcast().unwrap(),
6794 Error::MalformedCert(_)
6795 ));
6796
6797 // Cert::TryFrom<PacketParserResult>
6798 let ppr = PacketParser::from_bytes(&keyring)?;
6799 assert!(matches!(
6800 Cert::try_from(ppr).unwrap_err().downcast().unwrap(),
6801 Error::MalformedCert(_)
6802 ));
6803 Ok(())
6804 }
6805
6806 /// Tests whether the policy is applied to primary key binding
6807 /// signatures.
6808 #[test]
6809 fn issue_531() -> Result<()> {
6810 let cert =
6811 Cert::from_bytes(crate::tests::key("peter-sha1-backsig.pgp"))?;
6812 let p = unsafe { &crate::policy::NullPolicy::new() };
6813 assert_eq!(cert.with_policy(p, None)?.keys().for_signing().count(), 1);
6814 let mut p = crate::policy::StandardPolicy::new();
6815 p.reject_hash(HashAlgorithm::SHA1);
6816 assert_eq!(cert.with_policy(&p, None)?.keys().for_signing().count(), 0);
6817 Ok(())
6818 }
6819
6820 /// Tests whether expired primary key binding signatures are
6821 /// rejected.
6822 #[test]
6823 fn issue_539() -> Result<()> {
6824 let cert =
6825 Cert::from_bytes(crate::tests::key("peter-expired-backsig.pgp"))?;
6826 let p = unsafe { &crate::policy::NullPolicy::new() };
6827 assert_eq!(cert.with_policy(p, None)?.keys().for_signing().count(), 0);
6828 let p = &crate::policy::StandardPolicy::new();
6829 assert_eq!(cert.with_policy(p, None)?.keys().for_signing().count(), 0);
6830 Ok(())
6831 }
6832
6833 /// Tests whether signatures are properly deduplicated.
6834 #[test]
6835 fn issue_568() -> Result<()> {
6836 use crate::packet::signature::subpacket::*;
6837
6838 let (cert, _) = CertBuilder::general_purpose(
6839 Some("alice@example.org")).generate().unwrap();
6840 assert_eq!(cert.userids().count(), 1);
6841 assert_eq!(cert.subkeys().count(), 2);
6842 assert_eq!(cert.unknowns().count(), 0);
6843 assert_eq!(cert.bad_signatures().count(), 0);
6844 assert_eq!(cert.userids().next().unwrap().self_signatures().count(), 1);
6845 assert_eq!(cert.subkeys().next().unwrap().self_signatures().count(), 1);
6846 assert_eq!(cert.subkeys().nth(1).unwrap().self_signatures().count(), 1);
6847
6848 // Create a variant of cert where the signatures have
6849 // additional information in the unhashed area.
6850 let cert_b = cert.clone();
6851 let mut packets = crate::PacketPile::from(cert_b).into_children()
6852 .collect::<Vec<_>>();
6853 for p in packets.iter_mut() {
6854 if let Packet::Signature(sig) = p {
6855 assert_eq!(sig.hashed_area().subpackets(
6856 SubpacketTag::IssuerFingerprint).count(),
6857 1);
6858 sig.unhashed_area_mut().add(Subpacket::new(
6859 SubpacketValue::Issuer("AAAA BBBB CCCC DDDD".parse()?),
6860 false)?)?;
6861 }
6862 }
6863 let cert_b = Cert::from_packets(packets.into_iter())?;
6864 let cert = cert.merge_public_and_secret(cert_b)?;
6865 assert_eq!(cert.userids().count(), 1);
6866 assert_eq!(cert.subkeys().count(), 2);
6867 assert_eq!(cert.unknowns().count(), 0);
6868 assert_eq!(cert.bad_signatures().count(), 0);
6869 assert_eq!(cert.userids().next().unwrap().self_signatures().count(), 1);
6870 assert_eq!(cert.subkeys().next().unwrap().self_signatures().count(), 1);
6871 assert_eq!(cert.subkeys().nth(1).unwrap().self_signatures().count(), 1);
6872
6873 Ok(())
6874 }
6875
6876 /// Checks that missing or bad embedded signatures cause the
6877 /// signature to be considered bad.
6878 #[test]
6879 fn missing_backsig_is_bad() -> Result<()> {
6880 use crate::packet::{
6881 key::Key6,
6882 signature::{
6883 SignatureBuilder,
6884 subpacket::{Subpacket, SubpacketValue},
6885 },
6886 };
6887
6888 // We'll study this certificate, because it contains a
6889 // signing-capable subkey.
6890 let cert = crate::Cert::from_bytes(crate::tests::key(
6891 "emmelie-dorothea-dina-samantha-awina-ed25519.pgp"))?;
6892 let mut pp = crate::PacketPile::from_bytes(crate::tests::key(
6893 "emmelie-dorothea-dina-samantha-awina-ed25519.pgp"))?;
6894 assert_eq!(pp.children().count(), 5);
6895
6896 if let Some(Packet::Signature(sig)) = pp.path_ref_mut(&[4]) {
6897 // Add a bogus but plausible embedded signature subpacket.
6898 let key: key::SecretKey
6899 = Key6::generate_ecc(true, Curve::Ed25519)?.into();
6900 let mut pair = key.into_keypair()?;
6901
6902 sig.unhashed_area_mut().replace(Subpacket::new(
6903 SubpacketValue::EmbeddedSignature(
6904 SignatureBuilder::new(SignatureType::PrimaryKeyBinding)
6905 .sign_primary_key_binding(
6906 &mut pair,
6907 cert.primary_key().key(),
6908 cert.keys().subkeys().next().unwrap().key())?),
6909 false)?)?;
6910 } else {
6911 panic!("expected a signature");
6912 }
6913
6914 // Parse into cert.
6915 use std::convert::TryFrom;
6916 let malicious_cert = Cert::try_from(pp)?;
6917 // The subkey binding signature should no longer check out.
6918 let p = &crate::policy::StandardPolicy::new();
6919 assert_eq!(malicious_cert.with_policy(p, None)?.keys().subkeys()
6920 .for_signing().count(), 0);
6921 // Instead, it should be considered bad.
6922 assert_eq!(malicious_cert.bad_signatures().count(), 1);
6923 Ok(())
6924 }
6925
6926 /// Checks that multiple embedded signatures are correctly
6927 /// handled.
6928 #[test]
6929 fn multiple_embedded_signatures() -> Result<()> {
6930 use crate::packet::{
6931 key::Key6,
6932 signature::{
6933 SignatureBuilder,
6934 subpacket::{Subpacket, SubpacketValue},
6935 },
6936 };
6937
6938 // We'll study this certificate, because it contains a
6939 // signing-capable subkey.
6940 let cert = crate::Cert::from_bytes(crate::tests::key(
6941 "emmelie-dorothea-dina-samantha-awina-ed25519.pgp"))?;
6942
6943 // Add a bogus but plausible embedded signature subpacket with
6944 // this key.
6945 let key: key::SecretKey
6946 = Key6::generate_ecc(true, Curve::Ed25519)?.into();
6947 let mut pair = key.into_keypair()?;
6948
6949 // Create a malicious cert to merge in.
6950 let mut pp = crate::PacketPile::from_bytes(crate::tests::key(
6951 "emmelie-dorothea-dina-samantha-awina-ed25519.pgp"))?;
6952 assert_eq!(pp.children().count(), 5);
6953
6954 if let Some(Packet::Signature(sig)) = pp.path_ref_mut(&[4]) {
6955 // Prepend a bad backsig.
6956 let backsig = sig.embedded_signatures().next().unwrap().clone();
6957 sig.unhashed_area_mut().replace(Subpacket::new(
6958 SubpacketValue::EmbeddedSignature(
6959 SignatureBuilder::new(SignatureType::PrimaryKeyBinding)
6960 .sign_primary_key_binding(
6961 &mut pair,
6962 cert.primary_key().key(),
6963 cert.keys().subkeys().next().unwrap().key())?),
6964 false)?)?;
6965 sig.unhashed_area_mut().add(Subpacket::new(
6966 SubpacketValue::EmbeddedSignature(backsig), false)?)?;
6967 } else {
6968 panic!("expected a signature");
6969 }
6970
6971 // Parse into cert.
6972 use std::convert::TryFrom;
6973 let malicious_cert = Cert::try_from(pp)?;
6974 // The subkey binding signature should still be fine.
6975 let p = &crate::policy::StandardPolicy::new();
6976 assert_eq!(malicious_cert.with_policy(p, None)?.keys().subkeys()
6977 .for_signing().count(), 1);
6978 assert_eq!(malicious_cert.bad_signatures().count(), 0);
6979
6980 // Now try to merge it in.
6981 let merged = cert.clone().merge_public_and_secret(malicious_cert.clone())?;
6982 // The subkey binding signature should still be fine.
6983 assert_eq!(merged.with_policy(p, None)?.keys().subkeys()
6984 .for_signing().count(), 1);
6985 let sig = merged.with_policy(p, None)?.keys().subkeys()
6986 .for_signing().next().unwrap().binding_signature();
6987 assert_eq!(sig.embedded_signatures().count(), 2);
6988
6989 // Now the other way around.
6990 let merged = malicious_cert.clone().merge_public_and_secret(cert.clone())?;
6991 // The subkey binding signature should still be fine.
6992 assert_eq!(merged.with_policy(p, None)?.keys().subkeys()
6993 .for_signing().count(), 1);
6994 let sig = merged.with_policy(p, None)?.keys().subkeys()
6995 .for_signing().next().unwrap().binding_signature();
6996 assert_eq!(sig.embedded_signatures().count(), 2);
6997 Ok(())
6998 }
6999
7000 /// Checks that Cert::merge(cert, cert) == cert.
7001 #[test]
7002 fn issue_579() -> Result<()> {
7003 use std::convert::TryFrom;
7004 use crate::packet::signature::subpacket::SubpacketTag;
7005
7006 let mut pp = crate::PacketPile::from_bytes(crate::tests::key(
7007 "emmelie-dorothea-dina-samantha-awina-ed25519.pgp"))?;
7008 assert_eq!(pp.children().count(), 5);
7009 // Drop issuer information from the unhashed areas.
7010 if let Some(Packet::Signature(sig)) = pp.path_ref_mut(&[2]) {
7011 sig.unhashed_area_mut().remove_all(SubpacketTag::Issuer);
7012 } else {
7013 panic!("expected a signature");
7014 }
7015 if let Some(Packet::Signature(sig)) = pp.path_ref_mut(&[4]) {
7016 sig.unhashed_area_mut().remove_all(SubpacketTag::Issuer);
7017 } else {
7018 panic!("expected a signature");
7019 }
7020
7021 let cert = Cert::try_from(pp)?;
7022 assert_eq!(cert.clone().merge_public_and_secret(cert.clone())?, cert);
7023
7024 Ok(())
7025 }
7026
7027 /// Checks that Cert::merge_public ignores secret key material.
7028 #[test]
7029 fn merge_public() -> Result<()> {
7030 let cert =
7031 Cert::from_bytes(crate::tests::key("testy-new.pgp"))?;
7032 let key =
7033 Cert::from_bytes(crate::tests::key("testy-new-private.pgp"))?;
7034
7035 assert!(! cert.is_tsk());
7036 assert!(key.is_tsk());
7037
7038 // Secrets are ignored in `other`.
7039 let merged = cert.clone().merge_public(key.clone())?;
7040 assert!(! merged.is_tsk());
7041 assert_eq!(merged, cert);
7042
7043 // Secrets are retained in `self`.
7044 let merged = key.clone().merge_public(cert.clone())?;
7045 assert!(merged.is_tsk());
7046 assert_eq!(merged, key);
7047
7048 Ok(())
7049 }
7050
7051 /// Make sure we can parse a key where the primary key is its own
7052 /// subkeys.
7053 #[test]
7054 fn primary_key_is_subkey() -> Result<()> {
7055 let p = &crate::policy::StandardPolicy::new();
7056
7057 let cert =
7058 Cert::from_bytes(crate::tests::key("primary-key-is-also-subkey.pgp"))?;
7059
7060 // There should be three keys:
7061 //
7062 // Fingerprint: 8E8C 33FA 4626 3379 76D9 7978 069C 0C34 8DD8 2C19
7063 // Public-key algo: EdDSA Edwards-curve Digital Signature Algorithm
7064 // Public-key size: 256 bits
7065 // Secret key: Unencrypted
7066 // Creation time: 2018-06-11 14:12:09 UTC
7067 // Key flags: certification, signing
7068 //
7069 // Subkey: 8E8C 33FA 4626 3379 76D9 7978 069C 0C34 8DD8 2C19
7070 // Public-key algo: EdDSA Edwards-curve Digital Signature Algorithm
7071 // Public-key size: 256 bits
7072 // Secret key: Unencrypted
7073 // Creation time: 2018-06-11 14:12:09 UTC
7074 // Key flags: certification, signing
7075 //
7076 // Subkey: 061C 3CA4 4AFF 0EC5 8DC6 6E95 22E3 FAFE 96B5 6C32
7077 // Public-key algo: EdDSA Edwards-curve Digital Signature Algorithm
7078 // Public-key size: 256 bits
7079 // Secret key: Unencrypted
7080 // Creation time: 2018-08-27 10:55:43 UTC
7081 // Key flags: signing
7082 //
7083 // UserID: Emmelie Dorothea Dina Samantha Awina Ed25519
7084 assert_eq!(cert.keys().count(), 3);
7085
7086 // Make sure there is a subkey with the same fingerprint as
7087 // the primary key.
7088 assert!(cert.keys().subkeys().any(|k| {
7089 k.key().fingerprint() == cert.primary_key().key().fingerprint()
7090 }));
7091
7092 // Make sure the self sig is valid, too.
7093 assert_eq!(cert.keys().count(), 3);
7094
7095 let vc = cert.with_policy(p, None)?;
7096 assert!(vc.keys().subkeys().any(|k| {
7097 k.key().fingerprint() == vc.primary_key().key().fingerprint()
7098 }));
7099
7100 Ok(())
7101 }
7102
7103 /// Makes sure that certification approval key signatures are
7104 /// correctly handled.
7105 #[test]
7106 fn certificaton_approval_signatures() -> Result<()> {
7107 use crate::{
7108 packet::signature::SignatureBuilder,
7109 types::*,
7110 };
7111 let p = &crate::policy::StandardPolicy::new();
7112
7113 let (alice, _) = CertBuilder::new()
7114 .add_userid("alice@foo.com")
7115 .generate()?;
7116 let mut alice_signer =
7117 alice.primary_key().key().clone().parts_into_secret()?
7118 .into_keypair()?;
7119
7120 let (bob, _) = CertBuilder::new()
7121 .add_userid("bob@bar.com")
7122 .generate()?;
7123 let mut bob_signer =
7124 bob.primary_key().key().clone().parts_into_secret()?
7125 .into_keypair()?;
7126 let bob_pristine = bob.clone();
7127
7128 // Have Alice certify the binding between "bob@bar.com" and
7129 // Bob's key.
7130 let alice_certifies_bob
7131 = bob.userids().next().unwrap().userid().bind(
7132 &mut alice_signer, &bob,
7133 SignatureBuilder::new(SignatureType::GenericCertification))?;
7134 let bob = bob.insert_packets(vec![
7135 alice_certifies_bob.clone(),
7136 ])?.0;
7137
7138 assert_eq!(bob.with_policy(p, None)?.userids().next().unwrap()
7139 .certifications().count(), 1);
7140 assert_eq!(bob.with_policy(p, None)?.userids().next().unwrap()
7141 .approved_certifications().count(), 0);
7142
7143 // Have Bob attest that certification.
7144 let attestations =
7145 bob.userids().next().unwrap().approve_of_certifications(
7146 p,
7147 None,
7148 &mut bob_signer,
7149 vec![&alice_certifies_bob])?;
7150 assert_eq!(attestations.len(), 1);
7151 let attestation = attestations[0].clone();
7152
7153 let bob = bob.insert_packets(vec![
7154 attestation.clone(),
7155 ])?.0;
7156
7157 assert_eq!(bob.bad_signatures().count(), 0);
7158 assert_eq!(bob.userids().next().unwrap().certifications().next(),
7159 Some(&alice_certifies_bob));
7160 assert_eq!(bob.userids().next().unwrap().bundle().approvals().next().unwrap(),
7161 &attestation);
7162 assert_eq!(bob.with_policy(p, None)?.userids().next().unwrap()
7163 .certifications().count(), 1);
7164 assert_eq!(bob.with_policy(p, None)?.userids().next().unwrap()
7165 .approved_certifications().count(), 1);
7166
7167 // Check that attested key signatures are kept over merges.
7168 let bob_ = bob.clone().merge_public(bob_pristine.clone())?;
7169 assert_eq!(bob_.bad_signatures().count(), 0);
7170 assert_eq!(bob_.userids().next().unwrap().certifications().next(),
7171 Some(&alice_certifies_bob));
7172 assert_eq!(bob_.userids().next().unwrap().bundle().approvals().next().unwrap(),
7173 &attestation);
7174 assert_eq!(bob_.with_policy(p, None)?.userids().next().unwrap()
7175 .approved_certifications().count(), 1);
7176
7177 // And the other way around.
7178 let bob_ = bob_pristine.clone().merge_public(bob.clone())?;
7179 assert_eq!(bob_.bad_signatures().count(), 0);
7180 assert_eq!(bob_.userids().next().unwrap().certifications().next(),
7181 Some(&alice_certifies_bob));
7182 assert_eq!(bob_.userids().next().unwrap().bundle().approvals().next().unwrap(),
7183 &attestation);
7184 assert_eq!(bob_.with_policy(p, None)?.userids().next().unwrap()
7185 .approved_certifications().count(), 1);
7186
7187 // Have Bob withdraw any prior attestations.
7188
7189 let attestations =
7190 bob.userids().next().unwrap().approve_of_certifications(
7191 p,
7192 None,
7193 &mut bob_signer,
7194 &[])?;
7195 assert_eq!(attestations.len(), 1);
7196 let attestation = attestations[0].clone();
7197
7198 let bob = bob.insert_packets(vec![
7199 attestation.clone(),
7200 ])?.0;
7201
7202 assert_eq!(bob.bad_signatures().count(), 0);
7203 assert_eq!(bob.userids().next().unwrap().certifications().next(),
7204 Some(&alice_certifies_bob));
7205 assert_eq!(bob.userids().next().unwrap().bundle().approvals().next().unwrap(),
7206 &attestation);
7207 assert_eq!(bob.with_policy(p, None)?.userids().next().unwrap()
7208 .certifications().count(), 1);
7209 assert_eq!(bob.with_policy(p, None)?.userids().next().unwrap()
7210 .approved_certifications().count(), 0);
7211
7212
7213 Ok(())
7214 }
7215
7216 /// Makes sure that certification approval key signatures are
7217 /// correctly handled.
7218 #[test]
7219 fn certification_approval_key_signatures_dkgpg() -> Result<()> {
7220 const DUMP: bool = false;
7221 let p = &crate::policy::StandardPolicy::new();
7222
7223 let test = Cert::from_bytes(crate::tests::key("1pa3pc-dkgpg.pgp"))?;
7224 assert_eq!(test.bad_signatures().count(), 0);
7225 assert_eq!(test.userids().next().unwrap().certifications().count(),
7226 1);
7227 assert_eq!(test.userids().next().unwrap().bundle().approvals().count(),
7228 1);
7229
7230 let attestation =
7231 test.userids().next().unwrap().bundle().approvals().next().unwrap();
7232
7233 if DUMP {
7234 for (i, d) in attestation.approved_certifications()?.enumerate() {
7235 crate::fmt::hex::Dumper::new(std::io::stderr(), "")
7236 .write(d, format!("expected digest {}", i))?;
7237 }
7238 }
7239
7240 let digests: std::collections::HashSet<_> =
7241 attestation.approved_certifications()?.collect();
7242
7243 for (i, certification) in
7244 test.userids().next().unwrap().certifications().enumerate()
7245 {
7246 // Hash the certification.
7247 let mut h = attestation.hash_algo().context()?
7248 .for_signature(attestation.version());
7249 certification.hash_for_confirmation(&mut h)?;
7250 let digest = h.into_digest()?;
7251
7252 if DUMP {
7253 crate::fmt::hex::Dumper::new(std::io::stderr(), "")
7254 .write(&digest, format!("computed digest {}", i))?;
7255 }
7256
7257 assert!(digests.contains(&digest[..]));
7258 }
7259
7260 assert_eq!(test.with_policy(p, None)?.userids().next().unwrap()
7261 .certifications().count(), 1);
7262 assert_eq!(test.with_policy(p, None)?.userids().next().unwrap()
7263 .approved_certifications().count(), 1);
7264
7265 Ok(())
7266 }
7267
7268 /// Makes sure that certification approval key signatures are
7269 /// correctly reordered.
7270 #[test]
7271 fn certification_approval_key_signature_out_of_order() -> Result<()> {
7272 let p = &crate::policy::StandardPolicy::new();
7273
7274 let (alice, _) = CertBuilder::general_purpose(
7275 Some("alice@example.org")).generate().unwrap();
7276 assert!(alice.keys().subkeys().count() > 0);
7277 let mut alice_signer =
7278 alice.primary_key().key().clone().parts_into_secret()?
7279 .into_keypair()?;
7280
7281 // Now, create new attestation signatures.
7282 let mut attestation_signatures = Vec::new();
7283 for uid in alice.userids() {
7284 attestation_signatures.append(&mut uid.approve_of_certifications(
7285 p,
7286 None,
7287 &mut alice_signer,
7288 uid.certifications(),
7289 )?);
7290 }
7291
7292 // Add the new signatures. This appends the attestation
7293 // signature so that it is considered part of last component,
7294 // a subkey.
7295 let alice2 = alice.insert_packets(attestation_signatures)?.0;
7296
7297 // Now we make sure the attestation signature was correctly reordered.
7298 assert_eq!(alice2.bad_signatures().count(), 0);
7299 let ua = alice2.userids().next().unwrap();
7300 assert_eq!(ua.approvals().count(), 1);
7301
7302 Ok(())
7303 }
7304
7305 /// Makes sure that marker packets are ignored when parsing certs.
7306 #[test]
7307 fn marker_packets() -> Result<()> {
7308 let cert = Cert::from_bytes(crate::tests::key("neal.pgp"))?;
7309 let mut buf = Vec::new();
7310 Packet::Marker(Default::default()).serialize(&mut buf)?;
7311 cert.serialize(&mut buf)?;
7312
7313 let cert_ = Cert::from_bytes(&buf)?;
7314 assert_eq!(cert, cert_);
7315 Ok(())
7316 }
7317
7318 /// Checks that messing with a revocation signature merely
7319 /// invalidates the signature and keeps the cert's revocation
7320 /// status unchanged.
7321 #[test]
7322 fn issue_486() -> Result<()> {
7323 use crate::{
7324 crypto::mpi,
7325 types::RevocationStatus::*,
7326 packet::signature::Signature4,
7327 policy::StandardPolicy,
7328 };
7329 let p = &StandardPolicy::new();
7330
7331 let (cert, revocation) = CertBuilder::new().generate()?;
7332
7333 // Base case.
7334 let c = cert.clone().insert_packets(Some(revocation.clone()))?.0;
7335 if let Revoked(_) = c.revocation_status(p, None) {
7336 // cert is considered revoked
7337 } else {
7338 panic!("Should be revoked, but is not: {:?}",
7339 c.revocation_status(p, None));
7340 }
7341
7342 // Breaking the revocation signature by changing the MPIs.
7343 let c = cert.clone().insert_packets(Some(
7344 Signature4::new(
7345 revocation.typ(),
7346 revocation.pk_algo(),
7347 revocation.hash_algo(),
7348 revocation.hashed_area().clone(),
7349 revocation.unhashed_area().clone(),
7350 *revocation.digest_prefix(),
7351 // MPI is replaced with a dummy one
7352 mpi::Signature::RSA {
7353 s: mpi::MPI::from(vec![1, 2, 3])
7354 })))?.0;
7355 if let NotAsFarAsWeKnow = c.revocation_status(p, None) {
7356 assert_eq!(c.bad_signatures().count(), 1);
7357 } else {
7358 panic!("Should not be revoked, but is: {:?}",
7359 c.revocation_status(p, None));
7360 }
7361
7362 // Breaking the revocation signature by changing the MPIs and
7363 // the digest prefix.
7364 let c = cert.clone().insert_packets(Some(
7365 Signature4::new(
7366 revocation.typ(),
7367 revocation.pk_algo(),
7368 revocation.hash_algo(),
7369 revocation.hashed_area().clone(),
7370 revocation.unhashed_area().clone(),
7371 // Prefix replaced with a dummy one
7372 [0, 1],
7373 // MPI is replaced with a dummy one
7374 mpi::Signature::RSA {
7375 s: mpi::MPI::from(vec![1, 2, 3])
7376 })))?.0;
7377 if let NotAsFarAsWeKnow = c.revocation_status(p, None) {
7378 assert_eq!(c.bad_signatures().count(), 1);
7379 } else {
7380 panic!("Should not be revoked, but is: {:?}",
7381 c.revocation_status(p, None));
7382 }
7383
7384 Ok(())
7385 }
7386
7387 /// Tests v3 binding signatures.
7388 #[test]
7389 #[allow(deprecated)]
7390 fn v3_binding_signature() -> Result<()> {
7391 skip_unless_supported!(crate::types::PublicKeyAlgorithm::DSA);
7392
7393 let c = Cert::from_bytes(
7394 crate::tests::key("pgp5-dsa-elg-v3-subkey-binding.pgp"))?;
7395 assert_eq!(c.bad_signatures().count(), 0);
7396
7397 let np = unsafe { crate::policy::NullPolicy::new() };
7398
7399 // The subkey is interesting because it is bound using a v3
7400 // signature.
7401 let vcert = c.with_policy(&np, None)?;
7402 assert_eq!(vcert.keys().subkeys().count(), 1);
7403
7404 // A v3 signature has no subpackets, so there are no key
7405 // flags. But, we then consider the key role and public key
7406 // algorithm.
7407 assert_eq!(vcert.keys().for_signing().count(), 1);
7408 assert_eq!(vcert.keys().for_transport_encryption().count(), 1);
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 // A v3 signature has no subpackets, so there are no key
7415 // flags. But, we then consider the key role and public key
7416 // algorithm.
7417 assert_eq!(c.keys().with_policy(&np, None).for_signing().count(), 1);
7418 assert_eq!(c.keys().with_policy(&np, None)
7419 .for_transport_encryption().count(), 1);
7420
7421 Ok(())
7422 }
7423
7424 /// Tests v3 revocation signatures.
7425 #[test]
7426 fn v3_revocation_signature() -> Result<()> {
7427 skip_unless_supported!(crate::types::PublicKeyAlgorithm::ECDSA);
7428 skip_unless_supported!(crate::types::Curve::NistP521);
7429
7430 let c = Cert::from_bytes(
7431 crate::tests::key("v4-revoked-by-v3.pgp"))?;
7432 assert_eq!(c.bad_signatures().count(), 0);
7433
7434 let sp = crate::policy::StandardPolicy::new();
7435 assert!(matches!(c.revocation_status(&sp, None),
7436 RevocationStatus::Revoked(_)));
7437 Ok(())
7438 }
7439
7440 #[test]
7441 fn v6_minimal_cert() -> Result<()> {
7442 let p = &crate::policy::StandardPolicy::new();
7443 let t = None; // XXX
7444 let cert = Cert::from_bytes(
7445 crate::tests::file("crypto-refresh/v6-minimal-cert.key"))?;
7446 assert_eq!(cert.userids().count(), 0);
7447 let vcert = cert.with_policy(p, t)?;
7448 assert_eq!(vcert.keys().count(), 2);
7449 assert_eq!(vcert.keys().encrypted_secret().count(), 0);
7450 assert_eq!(vcert.keys().unencrypted_secret().count(), 0);
7451 assert_eq!(vcert.keys().for_signing().count(), 1);
7452 assert_eq!(vcert.keys().for_transport_encryption().count(), 1);
7453
7454 let cert = Cert::from_bytes(
7455 crate::tests::file("crypto-refresh/v6-minimal-secret.key")).unwrap();
7456 assert_eq!(cert.userids().count(), 0);
7457 let vcert = cert.with_policy(p, t)?;
7458 assert_eq!(vcert.keys().count(), 2);
7459 assert_eq!(vcert.keys().encrypted_secret().count(), 0);
7460 assert_eq!(vcert.keys().unencrypted_secret().count(), 2);
7461 assert_eq!(vcert.keys().for_signing().count(), 1);
7462 assert_eq!(vcert.keys().for_transport_encryption().count(), 1);
7463
7464 // The following key uses Argon2, and it takes 2 GiB to
7465 // efficiently derive the KEK. This isn't viable on 32 bit
7466 // architectures.
7467 let name = if cfg!(target_pointer_width = "16") {
7468 return Ok(()); // No chance we even got here.
7469 } else if cfg!(target_pointer_width = "32") {
7470 // For 32 bit architectures, we have a test vector which
7471 // uses the "SECOND RECOMMENDED" parameter choice for
7472 // memory constrained systems (see Section 4 of RFC 9106).
7473 "v6-minimal-secret-locked-for-constrained-envs.key"
7474 } else {
7475 // 64 bit or weird. Good luck.
7476 "v6-minimal-secret-locked.key"
7477 };
7478
7479 let cert = Cert::from_bytes(
7480 crate::tests::file(&format!("crypto-refresh/{}", name)))?;
7481 assert_eq!(cert.userids().count(), 0);
7482 let vcert = cert.with_policy(p, t)?;
7483 assert_eq!(vcert.keys().count(), 2);
7484 assert_eq!(vcert.keys().encrypted_secret().count(), 2);
7485 assert_eq!(vcert.keys().unencrypted_secret().count(), 0);
7486 assert_eq!(vcert.keys().for_signing().count(), 1);
7487 assert_eq!(vcert.keys().for_transport_encryption().count(), 1);
7488
7489 let password = "correct horse battery staple".into();
7490 for skb in vcert.keys().encrypted_secret() {
7491 skb.key().secret().clone().decrypt(skb.key(), &password)?;
7492 }
7493
7494 Ok(())
7495 }
7496}