Skip to main content

sequoia_openpgp/cert/
builder.rs

1use std::time;
2use std::marker::PhantomData;
3
4use crate::packet;
5use crate::packet::{
6    Key,
7    key::Key4,
8    key::Key6,
9    key::UnspecifiedRole,
10    key::SecretKey as KeySecretKey,
11    key::SecretParts as KeySecretParts,
12};
13use crate::Profile;
14use crate::Result;
15use crate::packet::Signature;
16use crate::packet::signature::{
17    self,
18    SignatureBuilder,
19    subpacket::SubpacketTag,
20};
21use crate::cert::prelude::*;
22use crate::Error;
23use crate::crypto::{Password, Signer};
24use crate::types::{
25    Features,
26    HashAlgorithm,
27    KeyFlags,
28    PublicKeyAlgorithmSpecification,
29    RevocationKey,
30    SignatureType,
31    SymmetricAlgorithm,
32};
33
34mod key;
35pub use key::{
36    KeyBuilder,
37    SubkeyBuilder,
38};
39
40/// Groups symmetric and asymmetric algorithms.
41///
42/// This is used to select a suite of ciphers.
43///
44/// # Examples
45///
46/// ```
47/// use sequoia_openpgp as openpgp;
48/// use openpgp::cert::prelude::*;
49/// use openpgp::types::PublicKeyAlgorithm;
50///
51/// # fn main() -> openpgp::Result<()> {
52/// let (ecc, _) =
53///     CertBuilder::general_purpose(Some("alice@example.org"))
54///         .set_cipher_suite(CipherSuite::Cv25519)
55///         .generate()?;
56/// assert_eq!(ecc.primary_key().key().pk_algo(), PublicKeyAlgorithm::EdDSA);
57///
58/// let (rsa, _) =
59///     CertBuilder::general_purpose(Some("alice@example.org"))
60///         .set_cipher_suite(CipherSuite::RSA4k)
61///         .generate()?;
62/// assert_eq!(rsa.primary_key().key().pk_algo(), PublicKeyAlgorithm::RSAEncryptSign);
63/// # Ok(())
64/// # }
65/// ```
66#[derive(Clone, Copy, PartialEq, Eq, Debug)]
67#[non_exhaustive]
68#[allow(non_camel_case_types)]
69pub enum CipherSuite {
70    /// EdDSA and ECDH over Curve25519 with SHA512 and AES256
71    Cv25519,
72    /// EdDSA and ECDH over Curve448 with SHA512 and AES256
73    Cv448,
74    /// 3072 bit RSA with SHA512 and AES256
75    RSA3k,
76    /// EdDSA and ECDH over NIST P-256 with SHA256 and AES256
77    P256,
78    /// EdDSA and ECDH over NIST P-384 with SHA384 and AES256
79    P384,
80    /// EdDSA and ECDH over NIST P-521 with SHA512 and AES256
81    P521,
82    /// 2048 bit RSA with SHA512 and AES256
83    RSA2k,
84    /// 4096 bit RSA with SHA512 and AES256
85    RSA4k,
86
87    /// Composite signature algorithm MLDSA65+Ed25519, and composite
88    /// KEM MLKEM768+X25519.
89    MLDSA65_Ed25519,
90
91    /// Composite signature algorithm MLDSA78+Ed448, and composite
92    /// KEM MLKEM1024+X448.
93    MLDSA87_Ed448,
94
95    // If you add a variant here, be sure to update
96    // CipherSuite::variants below.
97}
98assert_send_and_sync!(CipherSuite);
99
100impl Default for CipherSuite {
101    fn default() -> Self {
102        CipherSuite::Cv25519
103    }
104}
105
106impl CipherSuite {
107    /// Returns an iterator over `CipherSuite`'s  variants.
108    pub fn variants() -> impl Iterator<Item=CipherSuite> {
109        use CipherSuite::*;
110
111        [ Cv25519, Cv448, RSA3k, P256, P384, P521, RSA2k, RSA4k,
112          MLDSA65_Ed25519, MLDSA87_Ed448 ]
113            .into_iter()
114    }
115
116    /// Returns whether the currently selected cryptographic backend
117    /// supports the encryption and signing algorithms that the cipher
118    /// suite selects.
119    pub fn is_supported(&self) -> Result<()> {
120        use crate::types::{Curve, PublicKeyAlgorithm};
121        use CipherSuite::*;
122
123        macro_rules! check_pk {
124            ($pk: expr) => {
125                if ! $pk.is_supported() {
126                    return Err(Error::UnsupportedPublicKeyAlgorithm($pk)
127                               .into());
128                }
129            }
130        }
131
132        macro_rules! check_curve {
133            ($curve: expr) => {
134                if ! $curve.is_supported() {
135                    return Err(Error::UnsupportedEllipticCurve($curve)
136                               .into());
137                }
138            }
139        }
140
141        match self {
142            Cv25519 => {
143                check_pk!(PublicKeyAlgorithm::EdDSA);
144                check_curve!(Curve::Ed25519);
145                check_pk!(PublicKeyAlgorithm::ECDH);
146                check_curve!(Curve::Cv25519);
147            },
148            Cv448 => {
149                check_pk!(PublicKeyAlgorithm::X448);
150                check_pk!(PublicKeyAlgorithm::Ed448);
151            },
152            RSA2k | RSA3k | RSA4k => {
153                check_pk!(PublicKeyAlgorithm::RSAEncryptSign);
154            },
155            P256 => {
156                check_pk!(PublicKeyAlgorithm::ECDSA);
157                check_curve!(Curve::NistP256);
158                check_pk!(PublicKeyAlgorithm::ECDH);
159            },
160            P384 => {
161                check_pk!(PublicKeyAlgorithm::ECDSA);
162                check_curve!(Curve::NistP384);
163                check_pk!(PublicKeyAlgorithm::ECDH);
164            },
165            P521 => {
166                check_pk!(PublicKeyAlgorithm::ECDSA);
167                check_curve!(Curve::NistP521);
168                check_pk!(PublicKeyAlgorithm::ECDH);
169            },
170            MLDSA65_Ed25519 => {
171                check_pk!(PublicKeyAlgorithm::MLDSA65_Ed25519);
172                check_pk!(PublicKeyAlgorithm::MLKEM768_X25519);
173            }
174            MLDSA87_Ed448 => {
175                check_pk!(PublicKeyAlgorithm::MLDSA87_Ed448);
176                check_pk!(PublicKeyAlgorithm::MLKEM1024_X448);
177            }
178        }
179        Ok(())
180    }
181
182    fn generate_key<K>(self, flags: K, profile: Profile)
183        -> Result<Key<KeySecretParts, UnspecifiedRole>>
184        where K: AsRef<KeyFlags>,
185    {
186        match profile {
187            Profile::RFC9580 => Ok(self.generate_v6_key(flags)?.into()),
188            Profile::RFC4880 => Ok(self.generate_v4_key(flags)?.into()),
189        }
190    }
191
192    fn generate_v4_key<K>(self, flags: K)
193        -> Result<Key4<KeySecretParts, UnspecifiedRole>>
194        where K: AsRef<KeyFlags>,
195    {
196        use crate::types::Curve;
197
198        match self {
199            CipherSuite::RSA2k =>
200                Key4::generate_rsa(2048),
201            CipherSuite::RSA3k =>
202                Key4::generate_rsa(3072),
203            CipherSuite::RSA4k =>
204                Key4::generate_rsa(4096),
205            CipherSuite::Cv448 => {
206                let flags = flags.as_ref();
207                let sign = flags.for_certification() || flags.for_signing()
208                    || flags.for_authentication();
209                let encrypt = flags.for_transport_encryption()
210                    || flags.for_storage_encryption();
211                match (sign, encrypt) {
212                    (true, false) => Key4::generate_ed448(),
213                    (false, true) => Key4::generate_x448(),
214                    (true, true) =>
215                        Err(Error::InvalidOperation(
216                            "Can't use key for encryption and signing".into())
217                            .into()),
218                    (false, false) =>
219                        Err(Error::InvalidOperation(
220                            "No key flags set".into())
221                            .into()),
222                }
223            }
224            CipherSuite::Cv25519 | CipherSuite::P256 |
225            CipherSuite::P384 | CipherSuite::P521 => {
226                let flags = flags.as_ref();
227                let sign = flags.for_certification() || flags.for_signing()
228                    || flags.for_authentication();
229                let encrypt = flags.for_transport_encryption()
230                    || flags.for_storage_encryption();
231                let curve = match self {
232                    CipherSuite::Cv25519 if sign => Curve::Ed25519,
233                    CipherSuite::Cv25519 if encrypt => Curve::Cv25519,
234                    CipherSuite::Cv25519 => {
235                        return Err(Error::InvalidOperation(
236                            "No key flags set".into())
237                            .into());
238                    }
239                    CipherSuite::P256 => Curve::NistP256,
240                    CipherSuite::P384 => Curve::NistP384,
241                    CipherSuite::P521 => Curve::NistP521,
242                    _ => unreachable!(),
243                };
244
245                match (sign, encrypt) {
246                    (true, false) => Key4::generate_ecc(true, curve),
247                    (false, true) => Key4::generate_ecc(false, curve),
248                    (true, true) =>
249                        Err(Error::InvalidOperation(
250                            "Can't use key for encryption and signing".into())
251                            .into()),
252                    (false, false) =>
253                        Err(Error::InvalidOperation(
254                            "No key flags set".into())
255                            .into()),
256                }
257            },
258
259            CipherSuite::MLDSA65_Ed25519 | CipherSuite::MLDSA87_Ed448 =>
260                Err(Error::InvalidOperation(
261                    "can't use algorithms for v4 keys".into())
262                    .into()),
263        }
264    }
265
266    fn generate_v6_key<K>(self, flags: K)
267        -> Result<Key6<KeySecretParts, UnspecifiedRole>>
268        where K: AsRef<KeyFlags>,
269    {
270        use crate::types::Curve;
271
272        let flags = flags.as_ref();
273        let sign = flags.for_certification() || flags.for_signing()
274            || flags.for_authentication();
275        let encrypt = flags.for_transport_encryption()
276            || flags.for_storage_encryption();
277
278        match self {
279            CipherSuite::Cv25519 => match (sign, encrypt) {
280                (true, false) => Key6::generate_ed25519(),
281                (false, true) => Key6::generate_x25519(),
282                (true, true) =>
283                    Err(Error::InvalidOperation(
284                        "Can't use key for encryption and signing".into())
285                        .into()),
286                (false, false) =>
287                    Err(Error::InvalidOperation(
288                        "No key flags set".into())
289                        .into()),
290            },
291            CipherSuite::RSA2k =>
292                Key6::generate_rsa(2048),
293            CipherSuite::RSA3k =>
294                Key6::generate_rsa(3072),
295            CipherSuite::RSA4k =>
296                Key6::generate_rsa(4096),
297            CipherSuite::Cv448 => match (sign, encrypt) {
298                (true, false) => Key6::generate_ed448(),
299                (false, true) => Key6::generate_x448(),
300                (true, true) =>
301                    Err(Error::InvalidOperation(
302                        "Can't use key for encryption and signing".into())
303                        .into()),
304                (false, false) =>
305                    Err(Error::InvalidOperation(
306                        "No key flags set".into())
307                        .into()),
308            },
309            CipherSuite::P256 | CipherSuite::P384 | CipherSuite::P521 => {
310                let curve = match self {
311                    CipherSuite::Cv25519 if sign => Curve::Ed25519,
312                    CipherSuite::Cv25519 if encrypt => Curve::Cv25519,
313                    CipherSuite::Cv25519 => {
314                        return Err(Error::InvalidOperation(
315                            "No key flags set".into())
316                            .into());
317                    }
318                    CipherSuite::P256 => Curve::NistP256,
319                    CipherSuite::P384 => Curve::NistP384,
320                    CipherSuite::P521 => Curve::NistP521,
321                    _ => unreachable!(),
322                };
323
324                match (sign, encrypt) {
325                    (true, false) => Key6::generate_ecc(true, curve),
326                    (false, true) => Key6::generate_ecc(false, curve),
327                    (true, true) =>
328                        Err(Error::InvalidOperation(
329                            "Can't use key for encryption and signing".into())
330                            .into()),
331                    (false, false) =>
332                        Err(Error::InvalidOperation(
333                            "No key flags set".into())
334                            .into()),
335                }
336            },
337
338            a @ CipherSuite::MLDSA65_Ed25519 | a @ CipherSuite::MLDSA87_Ed448 =>
339                match (sign, encrypt, a) {
340                    (true, false, CipherSuite::MLDSA65_Ed25519) =>
341                        Key6::generate_mldsa65_ed25519(),
342                    (true, false, CipherSuite::MLDSA87_Ed448) =>
343                        Key6::generate_mldsa87_ed448(),
344                    (true, false, _) => unreachable!(),
345                    (false, true, CipherSuite::MLDSA65_Ed25519) =>
346                        Key6::generate_mlkem768_x25519(),
347                    (false, true, CipherSuite::MLDSA87_Ed448) =>
348                        Key6::generate_mlkem1024_x448(),
349                    (false, true, _) => unreachable!(),
350                    (true, true, _) =>
351                        Err(Error::InvalidOperation(
352                            "Can't use key for encryption and signing".into())
353                            .into()),
354                    (false, false, _) =>
355                        Err(Error::InvalidOperation(
356                            "No key flags set".into())
357                            .into()),
358                },
359        }
360    }
361}
362
363#[derive(Clone, Debug)]
364pub struct KeyBlueprint {
365    flags: KeyFlags,
366    validity: Option<time::Duration>,
367    // If not None, uses the specified ciphersuite.  Otherwise, uses
368    // CertBuilder::ciphersuite.
369    ciphersuite: Option<CipherSuite>,
370    for_signing: Option<PublicKeyAlgorithmSpecification>,
371    for_encryption: Option<PublicKeyAlgorithmSpecification>,
372}
373assert_send_and_sync!(KeyBlueprint);
374
375/// Simplifies the generation of OpenPGP certificates.
376///
377/// A builder to generate complex certificate hierarchies with multiple
378/// [`UserID`s], [`UserAttribute`s], and [`Key`s].
379///
380/// This builder does not aim to be as flexible as creating
381/// certificates manually, but it should be sufficiently powerful to
382/// cover most use cases.
383///
384/// [`UserID`s]: crate::packet::UserID
385/// [`UserAttribute`s]: crate::packet::user_attribute::UserAttribute
386/// [`Key`s]: crate::packet::Key
387///
388/// # Security considerations
389///
390/// ## Expiration
391///
392/// There are two ways to invalidate cryptographic key material:
393/// revocation and freshness.  Both variants come with their own
394/// challenges.  Revocations rely on a robust channel to update
395/// certificates (and attackers may interfere with that).
396///
397/// On the other hand, freshness involves creating key material that
398/// expires after a certain time, then periodically extending the
399/// expiration time.  Again, consumers need a way to update
400/// certificates, but should that fail (maybe because it was
401/// interfered with), the consumer errs on the side of no longer
402/// trusting that key material.
403///
404/// Because of the way metadata is added to OpenPGP certificates,
405/// attackers who control the certificate lookup and update mechanism
406/// may strip components like signatures from the certificate.  This
407/// has implications for the robustness of relying on freshness.
408///
409/// If you first create a certificate that does not expire, and then
410/// change your mind and set an expiration time, an attacker can
411/// simply strip off that update, yielding the original certificate
412/// that does not expire.
413///
414/// Hence, to ensure robust key expiration, you must set an expiration
415/// with [`CertBuilder::set_validity_period`] when you create the
416/// certificate.
417///
418/// By default, the `CertBuilder` creates certificates that do not
419/// expire, because the expiration time is a policy decision and
420/// depends on the use case.  For general purpose certificates,
421/// [`CertBuilder::general_purpose`] sets the validity period to
422/// roughly three years.
423///
424/// # Examples
425///
426/// Generate a general-purpose certificate with one User ID:
427///
428/// ```
429/// use sequoia_openpgp as openpgp;
430/// use openpgp::cert::prelude::*;
431///
432/// # fn main() -> openpgp::Result<()> {
433/// let (cert, rev) =
434///     CertBuilder::general_purpose(Some("alice@example.org"))
435///         .generate()?;
436/// # Ok(())
437/// # }
438/// ```
439///
440/// Generate a general-purpose certificate that uses post-quantum
441/// cryptography.  To do this, we select a post-quantum cipher suite,
442/// and we use the RFC 9580 profile, which is required for a
443/// post-quantum resistant certificate.
444///
445/// ```
446/// use sequoia_openpgp as openpgp;
447/// use openpgp::Profile;
448/// use openpgp::cert::CertBuilder;
449/// use openpgp::cert::CipherSuite;
450/// # use openpgp::types::PublicKeyAlgorithm;
451///
452/// # fn main() -> openpgp::Result<()> {
453/// # if ! PublicKeyAlgorithm::MLDSA65_Ed25519.is_supported()
454/// #     || ! PublicKeyAlgorithm::MLKEM768_X25519.is_supported()
455/// # {
456/// #     return Ok(());
457/// # }
458/// let (cert, rev) = CertBuilder::general_purpose(Some("<post-quantum@example.org>"))
459///     .set_profile(Profile::RFC9580)?
460///     .set_cipher_suite(CipherSuite::MLDSA65_Ed25519)
461///     .generate()?;
462/// # Ok(())
463/// # }
464/// ```
465pub struct CertBuilder<'a> {
466    creation_time: Option<std::time::SystemTime>,
467    ciphersuite: CipherSuite,
468    for_encryption: Option<PublicKeyAlgorithmSpecification>,
469    for_signing: Option<PublicKeyAlgorithmSpecification>,
470    profile: Profile,
471
472    /// Advertised features.
473    features: Features,
474    primary: KeyBlueprint,
475    subkeys: Vec<(Option<SignatureBuilder>, KeyBlueprint)>,
476    userids: Vec<(Option<SignatureBuilder>, packet::UserID)>,
477    user_attributes: Vec<(Option<SignatureBuilder>, packet::UserAttribute)>,
478    password: Option<Password>,
479    revocation_keys: Option<Vec<RevocationKey>>,
480    exportable: bool,
481    phantom: PhantomData<&'a ()>,
482}
483assert_send_and_sync!(CertBuilder<'_>);
484
485impl CertBuilder<'_> {
486    /// Returns a new `CertBuilder`.
487    ///
488    /// The returned builder is configured to generate a minimal
489    /// OpenPGP certificate, a certificate with just a
490    /// certification-capable primary key.  You'll typically want to
491    /// add at least one User ID (using
492    /// [`CertBuilder::add_userid`]). and some subkeys (using
493    /// [`CertBuilder::add_signing_subkey`],
494    /// [`CertBuilder::add_transport_encryption_subkey`], etc.).
495    ///
496    /// By default, the generated certificate does not expire.  It is
497    /// recommended to set a suitable validity period using
498    /// [`CertBuilder::set_validity_period`].  See [this
499    /// section](CertBuilder#expiration) of the type's documentation
500    /// for security considerations of key expiration.
501    ///
502    /// # Examples
503    ///
504    /// ```
505    /// use sequoia_openpgp as openpgp;
506    /// use openpgp::cert::prelude::*;
507    ///
508    /// # fn main() -> openpgp::Result<()> {
509    /// let (cert, rev) =
510    ///     CertBuilder::new()
511    ///         .add_userid("Alice Lovelace <alice@lovelace.name>")
512    ///         .add_signing_subkey()
513    ///         .add_transport_encryption_subkey()
514    ///         .add_storage_encryption_subkey()
515    ///         .generate()?;
516    /// # assert_eq!(cert.keys().count(), 1 + 3);
517    /// # assert_eq!(cert.userids().count(), 1);
518    /// # assert_eq!(cert.user_attributes().count(), 0);
519    /// # Ok(())
520    /// # }
521    /// ```
522    pub fn new() -> Self {
523        CertBuilder {
524            creation_time: None,
525            ciphersuite: CipherSuite::default(),
526            for_encryption: None,
527            for_signing: None,
528            profile: Default::default(),
529            features: Features::sequoia(),
530            primary: KeyBlueprint {
531                flags: KeyFlags::empty().set_certification(),
532                validity: None,
533                ciphersuite: None,
534                for_encryption: None,
535                for_signing: None,
536            },
537            subkeys: vec![],
538            userids: vec![],
539            user_attributes: vec![],
540            password: None,
541            revocation_keys: None,
542            exportable: true,
543            phantom: PhantomData,
544        }
545    }
546
547    /// Generates a general-purpose certificate.
548    ///
549    /// The returned builder is set to generate a certificate with a
550    /// certification-capable primary key, a signing-capable subkey,
551    /// and an encryption-capable subkey.  The encryption subkey is
552    /// marked as being appropriate for both data in transit and data
553    /// at rest.
554    ///
555    /// The certificate and all subkeys are valid for approximately
556    /// three years.
557    ///
558    /// # Examples
559    ///
560    /// ```
561    /// use sequoia_openpgp as openpgp;
562    /// use openpgp::cert::prelude::*;
563    ///
564    /// # fn main() -> openpgp::Result<()> {
565    /// let (cert, rev) =
566    ///     CertBuilder::general_purpose(["Alice Lovelace", "<alice@example.org>"])
567    ///         .generate()?;
568    /// # assert_eq!(cert.keys().count(), 3);
569    /// # assert_eq!(cert.userids().count(), 2);
570    ///
571    /// let (cert, rev) =
572    ///     CertBuilder::general_purpose(["Alice Lovelace <alice@example.org>"])
573    ///         .generate()?;
574    /// # assert_eq!(cert.keys().count(), 3);
575    /// # assert_eq!(cert.userids().count(), 1);
576    /// # Ok(())
577    /// # }
578    /// ```
579    pub fn general_purpose<U>(userids: U) -> Self
580    where
581        U: IntoIterator,
582        U::Item: Into<packet::UserID>,
583    {
584        let mut builder = Self::new()
585            .set_primary_key_flags(KeyFlags::empty().set_certification())
586            .set_validity_period(
587                time::Duration::new(3 * 52 * 7 * 24 * 60 * 60, 0))
588            .add_signing_subkey()
589            .add_subkey(KeyFlags::empty()
590                        .set_transport_encryption()
591                        .set_storage_encryption(), None, None);
592
593        for u in userids {
594            builder = builder.add_userid(u.into());
595        }
596
597        builder
598    }
599
600    /// Sets the creation time.
601    ///
602    /// If `creation_time` is not `None`, this causes the
603    /// `CertBuilder` to use that time when [`CertBuilder::generate`]
604    /// is called.  If it is `None`, the default, then the current
605    /// time minus 60 seconds is used as creation time.  Backdating
606    /// the certificate by a minute has the advantage that the
607    /// certificate can immediately be customized:
608    ///
609    /// In order to reliably override a binding signature, the
610    /// overriding binding signature must be newer than the existing
611    /// signature.  If, however, the existing signature is created
612    /// `now`, any newer signature must have a future creation time,
613    /// and is considered invalid by Sequoia.  To avoid this, we
614    /// backdate certificate creation times (and hence binding
615    /// signature creation times), so that there is "space" between
616    /// the creation time and now for signature updates.
617    ///
618    /// Warning: this function takes a [`SystemTime`].  A `SystemTime`
619    /// has a higher resolution, and a larger range than an OpenPGP
620    /// [`Timestamp`].  Assuming the `creation_time` is in range, it
621    /// will automatically be truncated to the nearest time that is
622    /// representable by a `Timestamp`.  If it is not in range,
623    /// [`generate`] will return an error.
624    ///
625    /// [`CertBuilder::generate`]: CertBuilder::generate()
626    /// [`SystemTime`]: std::time::SystemTime
627    /// [`Timestamp`]: crate::types::Timestamp
628    /// [`generate`]: CertBuilder::generate()
629    ///
630    /// # Examples
631    ///
632    /// Generate a backdated certificate:
633    ///
634    /// ```
635    /// use std::time::{SystemTime, Duration};
636    /// use std::convert::TryFrom;
637    ///
638    /// use sequoia_openpgp as openpgp;
639    /// use openpgp::cert::prelude::*;
640    /// use openpgp::types::Timestamp;
641    ///
642    /// # fn main() -> openpgp::Result<()> {
643    /// let t = SystemTime::now() - Duration::from_secs(365 * 24 * 60 * 60);
644    /// // Roundtrip the time so that the assert below works.
645    /// let t = SystemTime::from(Timestamp::try_from(t)?);
646    ///
647    /// let (cert, rev) =
648    ///     CertBuilder::general_purpose(Some("Alice Lovelace <alice@example.org>"))
649    ///         .set_creation_time(t)
650    ///         .generate()?;
651    /// assert_eq!(cert.primary_key().self_signatures().nth(0).unwrap()
652    ///            .signature_creation_time(),
653    ///            Some(t));
654    /// # Ok(())
655    /// # }
656    /// ```
657    pub fn set_creation_time<T>(mut self, creation_time: T) -> Self
658        where T: Into<Option<std::time::SystemTime>>,
659    {
660        self.creation_time = creation_time.into();
661        self
662    }
663
664    /// Returns the configured creation time, if any.
665    ///
666    /// # Examples
667    ///
668    /// ```
669    /// use std::time::SystemTime;
670    ///
671    /// use sequoia_openpgp as openpgp;
672    /// use openpgp::cert::prelude::*;
673    ///
674    /// # fn main() -> openpgp::Result<()> {
675    /// let mut builder = CertBuilder::new();
676    /// assert!(builder.creation_time().is_none());
677    ///
678    /// let now = std::time::SystemTime::now();
679    /// builder = builder.set_creation_time(Some(now));
680    /// assert_eq!(builder.creation_time(), Some(now));
681    ///
682    /// builder = builder.set_creation_time(None);
683    /// assert!(builder.creation_time().is_none());
684    /// # Ok(())
685    /// # }
686    /// ```
687    pub fn creation_time(&self) -> Option<std::time::SystemTime>
688    {
689        self.creation_time
690    }
691
692    /// Sets the default asymmetric algorithms.
693    ///
694    /// This method controls the set of algorithms that is used to
695    /// generate the certificate's keys.
696    ///
697    /// The set of cipher suites represent reasonable defaults and
698    /// combinations.  You can set a particular encryption algorithm
699    /// using [`CertBuilder::set_encryption_algorithm`], and a
700    /// particular signing algorithm using
701    /// [`CertBuilder::set_signing_algorithm`].
702    ///
703    /// # Examples
704    ///
705    /// ```
706    /// use sequoia_openpgp as openpgp;
707    /// use openpgp::cert::prelude::*;
708    /// use openpgp::types::PublicKeyAlgorithm;
709    ///
710    /// # fn main() -> openpgp::Result<()> {
711    /// let (ecc, _) =
712    ///     CertBuilder::general_purpose(Some("alice@example.org"))
713    ///         .set_cipher_suite(CipherSuite::Cv25519)
714    ///         .generate()?;
715    /// assert_eq!(ecc.primary_key().key().pk_algo(), PublicKeyAlgorithm::EdDSA);
716    ///
717    /// let (rsa, _) =
718    ///     CertBuilder::general_purpose(Some("alice@example.org"))
719    ///         .set_cipher_suite(CipherSuite::RSA2k)
720    ///         .generate()?;
721    /// assert_eq!(rsa.primary_key().key().pk_algo(), PublicKeyAlgorithm::RSAEncryptSign);
722    /// # Ok(())
723    /// # }
724    /// ```
725    pub fn set_cipher_suite(mut self, cs: CipherSuite) -> Self {
726        self.ciphersuite = cs;
727        self
728    }
729
730    /// Sets whether the certificate is exportable.
731    ///
732    /// This method controls whether the certificate is exportable.
733    /// If the certificate builder is configured to make a
734    /// non-exportable certificate, then all the signatures that it
735    /// creates include the [Exportable Certification] subpacket
736    /// that is set to `false`.
737    ///
738    /// [Exportable Certification]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.19
739    ///
740    /// # Examples
741    ///
742    /// When exporting a non-exportable certificate, nothing will be
743    /// exported.  This is also the case when the output is ASCII
744    /// armored.
745    ///
746    /// ```
747    /// use sequoia_openpgp as openpgp;
748    /// use openpgp::Result;
749    /// use openpgp::cert::prelude::*;
750    /// use openpgp::parse::Parse;
751    /// use openpgp::serialize::Serialize;
752    ///
753    /// # fn main() -> openpgp::Result<()> {
754    /// let (cert, _) =
755    ///     CertBuilder::general_purpose(Some("alice@example.org"))
756    ///         .set_exportable(false)
757    ///         .generate()?;
758    /// let mut exported = Vec::new();
759    /// cert.armored().export(&mut exported)?;
760    ///
761    /// let certs = CertParser::from_bytes(&exported)?
762    ///     .collect::<Result<Vec<Cert>>>()?;
763    /// assert_eq!(certs.len(), 0);
764    /// assert_eq!(exported.len(), 0, "{}", String::from_utf8_lossy(&exported));
765    /// # Ok(())
766    /// # }
767    /// ```
768    pub fn set_exportable(mut self, exportable: bool) -> Self {
769        self.exportable = exportable;
770        self
771    }
772
773    /// Sets the version of OpenPGP to generate keys for.
774    ///
775    /// Supported are [`Profile::RFC9580`] which will generate version
776    /// 6 keys, and [`Profile::RFC4880`] which will version 4 keys.
777    /// The default is the default value of [`Profile`].
778    ///
779    /// # Examples
780    ///
781    /// ```
782    /// use sequoia_openpgp as openpgp;
783    /// use openpgp::cert::prelude::*;
784    ///
785    /// # fn main() -> openpgp::Result<()> {
786    /// let (key, _) =
787    ///     CertBuilder::general_purpose(Some("alice@example.org"))
788    ///         .set_profile(openpgp::Profile::RFC9580)?
789    ///         .generate()?;
790    /// assert_eq!(key.primary_key().key().version(), 6);
791    ///
792    /// let (key, _) =
793    ///     CertBuilder::general_purpose(Some("bob@example.org"))
794    ///         .set_profile(openpgp::Profile::RFC4880)?
795    ///         .generate()?;
796    /// assert_eq!(key.primary_key().key().version(), 4);
797    /// # Ok(())
798    /// # }
799    /// ```
800    pub fn set_profile(mut self, profile: Profile) -> Result<Self> {
801        self.profile = profile;
802        Ok(self)
803    }
804
805    /// Sets the features the certificate will advertise.
806    ///
807    /// # Examples
808    ///
809    /// ```
810    /// use sequoia_openpgp as openpgp;
811    /// use openpgp::cert::prelude::*;
812    /// use openpgp::types::Features;
813    ///
814    /// # fn main() -> openpgp::Result<()> {
815    /// let (key, _) =
816    ///     CertBuilder::general_purpose(Some("alice@example.org"))
817    ///         .set_profile(openpgp::Profile::RFC9580)?
818    ///         .generate()?;
819    /// assert_eq!(key.primary_key().key().version(), 6);
820    ///
821    /// // Bob is old-school: he needs this key to work on an old
822    /// // phone.  Therefore, he doesn't want to get SEIPDv2 messages,
823    /// // which his phone doesn't handle.  He advertises support for
824    /// // SEIPDv1 only.
825    /// let (key, _) =
826    ///     CertBuilder::general_purpose(Some("bob@example.org"))
827    ///         .set_profile(openpgp::Profile::RFC4880)?
828    ///         .set_features(Features::empty().set_seipdv1())?
829    ///         .generate()?;
830    /// assert_eq!(key.primary_key().key().version(), 4);
831    /// # Ok(())
832    /// # }
833    /// ```
834    pub fn set_features(mut self, features: Features) -> Result<Self> {
835        self.features = features;
836        Ok(self)
837    }
838
839    /// Adds a User ID.
840    ///
841    /// Adds a User ID to the certificate.  The first User ID that is
842    /// added, whether via this interface or another interface, e.g.,
843    /// [`CertBuilder::general_purpose`], will have the [primary User
844    /// ID flag] set.
845    ///
846    /// [`CertBuilder::general_purpose`]: CertBuilder::general_purpose()
847    /// [primary User ID flag]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.27
848    ///
849    /// # Examples
850    ///
851    /// ```
852    /// use sequoia_openpgp as openpgp;
853    /// use openpgp::cert::prelude::*;
854    /// use openpgp::packet::prelude::*;
855    /// use openpgp::policy::StandardPolicy;
856    ///
857    /// # fn main() -> openpgp::Result<()> {
858    /// let p = &StandardPolicy::new();
859    ///
860    /// let (cert, rev) =
861    ///     CertBuilder::general_purpose(Some("Alice Lovelace <alice@example.org>"))
862    ///         .add_userid("Alice Lovelace <alice@lovelace.name>")
863    ///         .generate()?;
864    ///
865    /// assert_eq!(cert.userids().count(), 2);
866    /// let mut userids = cert.with_policy(p, None)?.userids().collect::<Vec<_>>();
867    /// // Sort lexicographically.
868    /// userids.sort_by(|a, b| a.userid().value().cmp(b.userid().value()));
869    /// assert_eq!(userids[0].userid(),
870    ///            &UserID::from("Alice Lovelace <alice@example.org>"));
871    /// assert_eq!(userids[1].userid(),
872    ///            &UserID::from("Alice Lovelace <alice@lovelace.name>"));
873    ///
874    ///
875    /// assert_eq!(userids[0].binding_signature().primary_userid().unwrap_or(false), true);
876    /// assert_eq!(userids[1].binding_signature().primary_userid().unwrap_or(false), false);
877    /// # Ok(())
878    /// # }
879    /// ```
880    pub fn add_userid<U>(mut self, uid: U) -> Self
881        where U: Into<packet::UserID>
882    {
883        self.userids.push((None, uid.into()));
884        self
885    }
886
887    /// Adds a User ID with a binding signature based on `builder`.
888    ///
889    /// Adds a User ID to the certificate, creating the binding
890    /// signature using `builder`.  The `builder`s signature type must
891    /// be a certification signature (i.e. either
892    /// [`GenericCertification`], [`PersonaCertification`],
893    /// [`CasualCertification`], or [`PositiveCertification`]).
894    ///
895    /// The key generation step uses `builder` as a template, but
896    /// tweaks it so the signature is a valid binding signature.  If
897    /// you need more control, consider using
898    /// [`UserID::bind`](crate::packet::UserID::bind).
899    ///
900    /// The following modifications are performed on `builder`:
901    ///
902    ///   - An appropriate hash algorithm is selected.
903    ///
904    ///   - The creation time is set.
905    ///
906    ///   - Primary key metadata is added (key flags, key validity period).
907    ///
908    ///   - Certificate metadata is added (feature flags, algorithm
909    ///     preferences).
910    ///
911    ///   - The [`CertBuilder`] marks exactly one User ID or User
912    ///     Attribute as primary: The first one provided to
913    ///     [`CertBuilder::add_userid_with`] or
914    ///     [`CertBuilder::add_user_attribute_with`] (the UserID takes
915    ///     precedence) that is marked as primary, or the first User
916    ///     ID or User Attribute added to the [`CertBuilder`].
917    ///
918    ///   [`GenericCertification`]: crate::types::SignatureType::GenericCertification
919    ///   [`PersonaCertification`]: crate::types::SignatureType::PersonaCertification
920    ///   [`CasualCertification`]: crate::types::SignatureType::CasualCertification
921    ///   [`PositiveCertification`]: crate::types::SignatureType::PositiveCertification
922    ///   [primary User ID flag]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.27
923    ///
924    /// # Examples
925    ///
926    /// This example very casually binds a User ID to a certificate.
927    ///
928    /// ```
929    /// # fn main() -> sequoia_openpgp::Result<()> {
930    /// # use sequoia_openpgp as openpgp;
931    /// # use openpgp::cert::prelude::*;
932    /// # use openpgp::packet::{prelude::*, signature::subpacket::*};
933    /// # use openpgp::policy::StandardPolicy;
934    /// # use openpgp::types::*;
935    /// # let policy = &StandardPolicy::new();
936    /// #
937    /// let (cert, revocation_cert) =
938    ///     CertBuilder::general_purpose(
939    ///         Some("Alice Lovelace <alice@example.org>"))
940    ///     .add_userid_with(
941    ///         "trinity",
942    ///         SignatureBuilder::new(SignatureType::CasualCertification)
943    ///             .set_notation("rabbit@example.org", b"follow me",
944    ///                           NotationDataFlags::empty().set_human_readable(),
945    ///                           false)?)?
946    ///     .generate()?;
947    ///
948    /// assert_eq!(cert.userids().count(), 2);
949    /// let mut userids = cert.with_policy(policy, None)?.userids().collect::<Vec<_>>();
950    /// // Sort lexicographically.
951    /// userids.sort_by(|a, b| a.userid().value().cmp(b.userid().value()));
952    /// assert_eq!(userids[0].userid(),
953    ///            &UserID::from("Alice Lovelace <alice@example.org>"));
954    /// assert_eq!(userids[1].userid(),
955    ///            &UserID::from("trinity"));
956    ///
957    /// assert!(userids[0].binding_signature().primary_userid().unwrap_or(false));
958    /// assert!(! userids[1].binding_signature().primary_userid().unwrap_or(false));
959    /// assert_eq!(userids[1].binding_signature().notation("rabbit@example.org")
960    ///            .next().unwrap(), b"follow me");
961    /// # Ok(()) }
962    /// ```
963    pub fn add_userid_with<U, B>(mut self, uid: U, builder: B)
964                                 -> Result<Self>
965    where U: Into<packet::UserID>,
966          B: Into<SignatureBuilder>,
967    {
968        let builder = builder.into();
969        match builder.typ() {
970            SignatureType::GenericCertification
971                | SignatureType::PersonaCertification
972                | SignatureType::CasualCertification
973                | SignatureType::PositiveCertification =>
974            {
975                self.userids.push((Some(builder), uid.into()));
976                Ok(self)
977            },
978            t =>
979                Err(Error::InvalidArgument(format!(
980                    "Signature type is not a certification: {}", t)).into()),
981        }
982    }
983
984    /// Adds a new User Attribute.
985    ///
986    /// Adds a User Attribute to the certificate.  If there are no
987    /// User IDs, the first User attribute that is added, whether via
988    /// this interface or another interface, will have the [primary
989    /// User ID flag] set.
990    ///
991    /// [primary User ID flag]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.27
992    ///
993    /// # Examples
994    ///
995    /// When there are no User IDs, the first User Attribute has the
996    /// primary User ID flag set:
997    ///
998    /// ```
999    /// # use openpgp::packet::user_attribute::Subpacket;
1000    /// use sequoia_openpgp as openpgp;
1001    /// use openpgp::cert::prelude::*;
1002    /// use openpgp::packet::prelude::*;
1003    /// use openpgp::policy::StandardPolicy;
1004    ///
1005    /// # fn main() -> openpgp::Result<()> {
1006    /// let p = &StandardPolicy::new();
1007    /// #
1008    /// # // Create some user attribute. Doctests do not pass cfg(test),
1009    /// # // so UserAttribute::arbitrary is not available
1010    /// # let sp = Subpacket::Unknown(7, vec![7; 7].into_boxed_slice());
1011    /// # let user_attribute = UserAttribute::new(&[sp])?;
1012    ///
1013    /// let (cert, rev) =
1014    ///     CertBuilder::new()
1015    ///         .add_user_attribute(user_attribute)
1016    ///         .generate()?;
1017    ///
1018    /// assert_eq!(cert.userids().count(), 0);
1019    /// assert_eq!(cert.user_attributes().count(), 1);
1020    /// let mut uas = cert.with_policy(p, None)?.user_attributes().collect::<Vec<_>>();
1021    /// assert_eq!(uas[0].binding_signature().primary_userid().unwrap_or(false), true);
1022    /// # Ok(())
1023    /// # }
1024    /// ```
1025    ///
1026    /// Where there are User IDs, then the primary User ID flag is not
1027    /// set:
1028    ///
1029    /// ```
1030    /// # use openpgp::packet::user_attribute::Subpacket;
1031    /// use sequoia_openpgp as openpgp;
1032    /// use openpgp::cert::prelude::*;
1033    /// use openpgp::packet::prelude::*;
1034    /// use openpgp::policy::StandardPolicy;
1035    ///
1036    /// # fn main() -> openpgp::Result<()> {
1037    /// let p = &StandardPolicy::new();
1038    /// #
1039    /// # // Create some user attribute. Doctests do not pass cfg(test),
1040    /// # // so UserAttribute::arbitrary is not available
1041    /// # let sp = Subpacket::Unknown(7, vec![7; 7].into_boxed_slice());
1042    /// # let user_attribute = UserAttribute::new(&[sp])?;
1043    ///
1044    /// let (cert, rev) =
1045    ///     CertBuilder::new()
1046    ///         .add_userid("alice@example.org")
1047    ///         .add_user_attribute(user_attribute)
1048    ///         .generate()?;
1049    ///
1050    /// assert_eq!(cert.userids().count(), 1);
1051    /// assert_eq!(cert.user_attributes().count(), 1);
1052    /// let mut uas = cert.with_policy(p, None)?.user_attributes().collect::<Vec<_>>();
1053    /// assert_eq!(uas[0].binding_signature().primary_userid().unwrap_or(false), false);
1054    /// # Ok(())
1055    /// # }
1056    /// ```
1057    pub fn add_user_attribute<U>(mut self, ua: U) -> Self
1058        where U: Into<packet::UserAttribute>
1059    {
1060        self.user_attributes.push((None, ua.into()));
1061        self
1062    }
1063
1064    /// Adds a User Attribute with a binding signature based on `builder`.
1065    ///
1066    /// Adds a User Attribute to the certificate, creating the binding
1067    /// signature using `builder`.  The `builder`s signature type must
1068    /// be a certification signature (i.e. either
1069    /// [`GenericCertification`], [`PersonaCertification`],
1070    /// [`CasualCertification`], or [`PositiveCertification`]).
1071    ///
1072    /// The key generation step uses `builder` as a template, but
1073    /// tweaks it so the signature is a valid binding signature.  If
1074    /// you need more control, consider using
1075    /// [`UserAttribute::bind`](crate::packet::UserAttribute::bind).
1076    ///
1077    /// The following modifications are performed on `builder`:
1078    ///
1079    ///   - An appropriate hash algorithm is selected.
1080    ///
1081    ///   - The creation time is set.
1082    ///
1083    ///   - Primary key metadata is added (key flags, key validity period).
1084    ///
1085    ///   - Certificate metadata is added (feature flags, algorithm
1086    ///     preferences).
1087    ///
1088    ///   - The [`CertBuilder`] marks exactly one User ID or User
1089    ///     Attribute as primary: The first one provided to
1090    ///     [`CertBuilder::add_userid_with`] or
1091    ///     [`CertBuilder::add_user_attribute_with`] (the UserID takes
1092    ///     precedence) that is marked as primary, or the first User
1093    ///     ID or User Attribute added to the [`CertBuilder`].
1094    ///
1095    ///   [`GenericCertification`]: crate::types::SignatureType::GenericCertification
1096    ///   [`PersonaCertification`]: crate::types::SignatureType::PersonaCertification
1097    ///   [`CasualCertification`]: crate::types::SignatureType::CasualCertification
1098    ///   [`PositiveCertification`]: crate::types::SignatureType::PositiveCertification
1099    ///   [primary User ID flag]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.27
1100    ///
1101    /// # Examples
1102    ///
1103    /// This example very casually binds a user attribute to a
1104    /// certificate.
1105    ///
1106    /// ```
1107    /// # fn main() -> sequoia_openpgp::Result<()> {
1108    /// # use sequoia_openpgp as openpgp;
1109    /// # use openpgp::packet::user_attribute::Subpacket;
1110    /// # use openpgp::cert::prelude::*;
1111    /// # use openpgp::packet::{prelude::*, signature::subpacket::*};
1112    /// # use openpgp::policy::StandardPolicy;
1113    /// # use openpgp::types::*;
1114    /// #
1115    /// # let policy = &StandardPolicy::new();
1116    /// #
1117    /// # // Create some user attribute. Doctests do not pass cfg(test),
1118    /// # // so UserAttribute::arbitrary is not available
1119    /// # let user_attribute =
1120    /// #   UserAttribute::new(&[Subpacket::Unknown(7, vec![7; 7].into())])?;
1121    /// let (cert, revocation_cert) =
1122    ///     CertBuilder::general_purpose(
1123    ///         Some("Alice Lovelace <alice@example.org>"))
1124    ///     .add_user_attribute_with(
1125    ///         user_attribute,
1126    ///         SignatureBuilder::new(SignatureType::CasualCertification)
1127    ///             .set_notation("rabbit@example.org", b"follow me",
1128    ///                           NotationDataFlags::empty().set_human_readable(),
1129    ///                           false)?)?
1130    ///     .generate()?;
1131    ///
1132    /// let uas = cert.with_policy(policy, None)?.user_attributes().collect::<Vec<_>>();
1133    /// assert_eq!(uas.len(), 1);
1134    /// assert!(! uas[0].binding_signature().primary_userid().unwrap_or(false));
1135    /// assert_eq!(uas[0].binding_signature().notation("rabbit@example.org")
1136    ///            .next().unwrap(), b"follow me");
1137    /// # Ok(()) }
1138    /// ```
1139    pub fn add_user_attribute_with<U, B>(mut self, ua: U, builder: B)
1140                                         -> Result<Self>
1141    where U: Into<packet::UserAttribute>,
1142          B: Into<SignatureBuilder>,
1143    {
1144        let builder = builder.into();
1145        match builder.typ() {
1146            SignatureType::GenericCertification
1147                | SignatureType::PersonaCertification
1148                | SignatureType::CasualCertification
1149                | SignatureType::PositiveCertification =>
1150            {
1151                self.user_attributes.push((Some(builder), ua.into()));
1152                Ok(self)
1153            },
1154            t =>
1155                Err(Error::InvalidArgument(format!(
1156                    "Signature type is not a certification: {}", t)).into()),
1157        }
1158    }
1159
1160    /// Adds a signing-capable subkey.
1161    ///
1162    /// The key uses the default cipher suite (see
1163    /// [`CertBuilder::set_cipher_suite`]), and is not set to expire.
1164    /// Use [`CertBuilder::add_subkey`] if you need to change these
1165    /// parameters.
1166    ///
1167    /// [`CertBuilder::set_cipher_suite`]: CertBuilder::set_cipher_suite()
1168    /// [`CertBuilder::add_subkey`]: CertBuilder::add_subkey()
1169    ///
1170    /// # Examples
1171    ///
1172    /// ```
1173    /// use sequoia_openpgp as openpgp;
1174    /// use openpgp::cert::prelude::*;
1175    /// use openpgp::policy::StandardPolicy;
1176    /// use openpgp::types::KeyFlags;
1177    ///
1178    /// # fn main() -> openpgp::Result<()> {
1179    /// let p = &StandardPolicy::new();
1180    ///
1181    /// let (cert, rev) =
1182    ///     CertBuilder::new()
1183    ///         .add_signing_subkey()
1184    ///         .generate()?;
1185    ///
1186    /// assert_eq!(cert.keys().count(), 2);
1187    /// let ka = cert.with_policy(p, None)?.keys().nth(1).unwrap();
1188    /// assert_eq!(ka.key_flags(),
1189    ///            Some(KeyFlags::empty().set_signing()));
1190    /// # Ok(())
1191    /// # }
1192    /// ```
1193    pub fn add_signing_subkey(self) -> Self {
1194        self.add_subkey(KeyFlags::empty().set_signing(), None, None)
1195    }
1196
1197    /// Adds a subkey suitable for transport encryption.
1198    ///
1199    /// The key uses the default cipher suite (see
1200    /// [`CertBuilder::set_cipher_suite`]), and is not set to expire.
1201    /// Use [`CertBuilder::add_subkey`] if you need to change these
1202    /// parameters.
1203    ///
1204    /// [`CertBuilder::set_cipher_suite`]: CertBuilder::set_cipher_suite()
1205    /// [`CertBuilder::add_subkey`]: CertBuilder::add_subkey()
1206    ///
1207    ///
1208    /// # Examples
1209    ///
1210    /// ```
1211    /// use sequoia_openpgp as openpgp;
1212    /// use openpgp::cert::prelude::*;
1213    /// use openpgp::policy::StandardPolicy;
1214    /// use openpgp::types::KeyFlags;
1215    ///
1216    /// # fn main() -> openpgp::Result<()> {
1217    /// let p = &StandardPolicy::new();
1218    ///
1219    /// let (cert, rev) =
1220    ///     CertBuilder::new()
1221    ///         .add_transport_encryption_subkey()
1222    ///         .generate()?;
1223    ///
1224    /// assert_eq!(cert.keys().count(), 2);
1225    /// let ka = cert.with_policy(p, None)?.keys().nth(1).unwrap();
1226    /// assert_eq!(ka.key_flags(),
1227    ///            Some(KeyFlags::empty().set_transport_encryption()));
1228    /// # Ok(())
1229    /// # }
1230    /// ```
1231    pub fn add_transport_encryption_subkey(self) -> Self {
1232        self.add_subkey(KeyFlags::empty().set_transport_encryption(),
1233                        None, None)
1234    }
1235
1236    /// Adds a subkey suitable for storage encryption.
1237    ///
1238    /// The key uses the default cipher suite (see
1239    /// [`CertBuilder::set_cipher_suite`]), and is not set to expire.
1240    /// Use [`CertBuilder::add_subkey`] if you need to change these
1241    /// parameters.
1242    ///
1243    /// [`CertBuilder::set_cipher_suite`]: CertBuilder::set_cipher_suite()
1244    /// [`CertBuilder::add_subkey`]: CertBuilder::add_subkey()
1245    ///
1246    ///
1247    /// # Examples
1248    ///
1249    /// ```
1250    /// use sequoia_openpgp as openpgp;
1251    /// use openpgp::cert::prelude::*;
1252    /// use openpgp::policy::StandardPolicy;
1253    /// use openpgp::types::KeyFlags;
1254    ///
1255    /// # fn main() -> openpgp::Result<()> {
1256    /// let p = &StandardPolicy::new();
1257    ///
1258    /// let (cert, rev) =
1259    ///     CertBuilder::new()
1260    ///         .add_storage_encryption_subkey()
1261    ///         .generate()?;
1262    ///
1263    /// assert_eq!(cert.keys().count(), 2);
1264    /// let ka = cert.with_policy(p, None)?.keys().nth(1).unwrap();
1265    /// assert_eq!(ka.key_flags(),
1266    ///            Some(KeyFlags::empty().set_storage_encryption()));
1267    /// # Ok(())
1268    /// # }
1269    /// ```
1270    pub fn add_storage_encryption_subkey(self) -> Self {
1271        self.add_subkey(KeyFlags::empty().set_storage_encryption(),
1272                        None, None)
1273    }
1274
1275    /// Adds a certification-capable subkey.
1276    ///
1277    /// The key uses the default cipher suite (see
1278    /// [`CertBuilder::set_cipher_suite`]), and is not set to expire.
1279    /// Use [`CertBuilder::add_subkey`] if you need to change these
1280    /// parameters.
1281    ///
1282    /// [`CertBuilder::set_cipher_suite`]: CertBuilder::set_cipher_suite()
1283    /// [`CertBuilder::add_subkey`]: CertBuilder::add_subkey()
1284    ///
1285    ///
1286    /// # Examples
1287    ///
1288    /// ```
1289    /// use sequoia_openpgp as openpgp;
1290    /// use openpgp::cert::prelude::*;
1291    /// use openpgp::policy::StandardPolicy;
1292    /// use openpgp::types::KeyFlags;
1293    ///
1294    /// # fn main() -> openpgp::Result<()> {
1295    /// let p = &StandardPolicy::new();
1296    ///
1297    /// let (cert, rev) =
1298    ///     CertBuilder::new()
1299    ///         .add_certification_subkey()
1300    ///         .generate()?;
1301    ///
1302    /// assert_eq!(cert.keys().count(), 2);
1303    /// let ka = cert.with_policy(p, None)?.keys().nth(1).unwrap();
1304    /// assert_eq!(ka.key_flags(),
1305    ///            Some(KeyFlags::empty().set_certification()));
1306    /// # Ok(())
1307    /// # }
1308    /// ```
1309    pub fn add_certification_subkey(self) -> Self {
1310        self.add_subkey(KeyFlags::empty().set_certification(), None, None)
1311    }
1312
1313    /// Adds an authentication-capable subkey.
1314    ///
1315    /// The key uses the default cipher suite (see
1316    /// [`CertBuilder::set_cipher_suite`]), and is not set to expire.
1317    /// Use [`CertBuilder::add_subkey`] if you need to change these
1318    /// parameters.
1319    ///
1320    /// [`CertBuilder::set_cipher_suite`]: CertBuilder::set_cipher_suite()
1321    /// [`CertBuilder::add_subkey`]: CertBuilder::add_subkey()
1322    ///
1323    ///
1324    /// # Examples
1325    ///
1326    /// ```
1327    /// use sequoia_openpgp as openpgp;
1328    /// use openpgp::cert::prelude::*;
1329    /// use openpgp::policy::StandardPolicy;
1330    /// use openpgp::types::KeyFlags;
1331    ///
1332    /// # fn main() -> openpgp::Result<()> {
1333    /// let p = &StandardPolicy::new();
1334    ///
1335    /// let (cert, rev) =
1336    ///     CertBuilder::new()
1337    ///         .add_authentication_subkey()
1338    ///         .generate()?;
1339    ///
1340    /// assert_eq!(cert.keys().count(), 2);
1341    /// let ka = cert.with_policy(p, None)?.keys().nth(1).unwrap();
1342    /// assert_eq!(ka.key_flags(),
1343    ///            Some(KeyFlags::empty().set_authentication()));
1344    /// # Ok(())
1345    /// # }
1346    /// ```
1347    pub fn add_authentication_subkey(self) -> Self {
1348        self.add_subkey(KeyFlags::empty().set_authentication(), None, None)
1349    }
1350
1351    /// Adds a custom subkey.
1352    ///
1353    /// If `validity` is `None`, the subkey will be valid for the same
1354    /// period as the primary key.
1355    ///
1356    /// Likewise, if `cs` is `None`, the same cipher suite is used as
1357    /// for the primary key.
1358    ///
1359    /// # Examples
1360    ///
1361    /// Generates a certificate with an encryption subkey that is for
1362    /// protecting *both* data in transit and data at rest, and
1363    /// expires at a different time from the primary key:
1364    ///
1365    /// ```
1366    /// use sequoia_openpgp as openpgp;
1367    /// # use openpgp::Result;
1368    /// use openpgp::cert::prelude::*;
1369    /// use openpgp::policy::StandardPolicy;
1370    /// use openpgp::types::KeyFlags;
1371    ///
1372    /// # fn main() -> Result<()> {
1373    /// let p = &StandardPolicy::new();
1374    ///
1375    /// let now = std::time::SystemTime::now();
1376    /// let y = std::time::Duration::new(365 * 24 * 60 * 60, 0);
1377    ///
1378    /// // Make the certificate expire in 2 years, and the subkey
1379    /// // expire in a year.
1380    /// let (cert,_) = CertBuilder::new()
1381    ///     .set_creation_time(now)
1382    ///     .set_validity_period(2 * y)
1383    ///     .add_subkey(KeyFlags::empty()
1384    ///                     .set_storage_encryption()
1385    ///                     .set_transport_encryption(),
1386    ///                 y,
1387    ///                 None)
1388    ///     .generate()?;
1389    ///
1390    /// assert_eq!(cert.with_policy(p, now)?.keys().alive().count(), 2);
1391    /// assert_eq!(cert.with_policy(p, now + y)?.keys().alive().count(), 1);
1392    /// assert_eq!(cert.with_policy(p, now + 2 * y)?.keys().alive().count(), 0);
1393    ///
1394    /// let ka = cert.with_policy(p, None)?.keys().nth(1).unwrap();
1395    /// assert_eq!(ka.key_flags(),
1396    ///            Some(KeyFlags::empty()
1397    ///                     .set_storage_encryption()
1398    ///                     .set_transport_encryption()));
1399    /// # Ok(()) }
1400    /// ```
1401    pub fn add_subkey<T, C>(mut self, flags: KeyFlags, validity: T, cs: C)
1402        -> Self
1403        where T: Into<Option<time::Duration>>,
1404              C: Into<Option<CipherSuite>>,
1405    {
1406        self.subkeys.push((None, KeyBlueprint {
1407            flags,
1408            validity: validity.into(),
1409            ciphersuite: cs.into(),
1410            for_encryption: None,
1411            for_signing: None,
1412        }));
1413        self
1414    }
1415
1416    /// Adds a subkey with a binding signature based on `builder`.
1417    ///
1418    /// Adds a subkey to the certificate, creating the binding
1419    /// signature using `builder`.  The `builder`s signature type must
1420    /// be [`SubkeyBinding`].
1421    ///
1422    /// The key generation step uses `builder` as a template, but adds
1423    /// all subpackets that the signature needs to be a valid binding
1424    /// signature.  If you need more control, or want to adopt
1425    /// existing keys, consider using
1426    /// [`Key::bind`](crate::packet::Key::bind).
1427    ///
1428    /// The following modifications are performed on `builder`:
1429    ///
1430    ///   - An appropriate hash algorithm is selected.
1431    ///
1432    ///   - The creation time is set.
1433    ///
1434    ///   - Key metadata is added (key flags, key validity period).
1435    ///
1436    ///   [`SubkeyBinding`]: crate::types::SignatureType::SubkeyBinding
1437    ///
1438    /// If `validity` is `None`, the subkey will be valid for the same
1439    /// period as the primary key.
1440    ///
1441    /// # Examples
1442    ///
1443    /// This example binds a signing subkey to a certificate,
1444    /// restricting its use to authentication of software.
1445    ///
1446    /// ```
1447    /// # fn main() -> sequoia_openpgp::Result<()> {
1448    /// # use sequoia_openpgp as openpgp;
1449    /// # use openpgp::packet::user_attribute::Subpacket;
1450    /// # use openpgp::cert::prelude::*;
1451    /// # use openpgp::packet::{prelude::*, signature::subpacket::*};
1452    /// # use openpgp::policy::StandardPolicy;
1453    /// # use openpgp::types::*;
1454    /// let (cert, revocation_cert) =
1455    ///     CertBuilder::general_purpose(
1456    ///         Some("Alice Lovelace <alice@example.org>"))
1457    ///     .add_subkey_with(
1458    ///         KeyFlags::empty().set_signing(), None, None,
1459    ///         SignatureBuilder::new(SignatureType::SubkeyBinding)
1460    ///             // Add a critical notation!
1461    ///             .set_notation("code-signing@policy.example.org", b"",
1462    ///                           NotationDataFlags::empty(), true)?)?
1463    ///     .generate()?;
1464    ///
1465    /// // Under the standard policy, the additional signing subkey
1466    /// // is not bound.
1467    /// let p = StandardPolicy::new();
1468    /// assert_eq!(cert.with_policy(&p, None)?.keys().for_signing().count(), 1);
1469    ///
1470    /// // However, software implementing the notation see the additional
1471    /// // signing subkey.
1472    /// let mut p = StandardPolicy::new();
1473    /// p.good_critical_notations(&["code-signing@policy.example.org"]);
1474    /// assert_eq!(cert.with_policy(&p, None)?.keys().for_signing().count(), 2);
1475    /// # Ok(()) }
1476    /// ```
1477    pub fn add_subkey_with<T, C, B>(mut self, flags: KeyFlags, validity: T,
1478                                    cs: C, builder: B) -> Result<Self>
1479        where T: Into<Option<time::Duration>>,
1480              C: Into<Option<CipherSuite>>,
1481              B: Into<SignatureBuilder>,
1482    {
1483        let builder = builder.into();
1484        match builder.typ() {
1485            SignatureType::SubkeyBinding => {
1486                self.subkeys.push((Some(builder), KeyBlueprint {
1487                    flags,
1488                    validity: validity.into(),
1489                    ciphersuite: cs.into(),
1490                    for_encryption: None,
1491                    for_signing: None,
1492                }));
1493                Ok(self)
1494            },
1495            t =>
1496                Err(Error::InvalidArgument(format!(
1497                    "Signature type is not a subkey binding: {}", t)).into()),
1498        }
1499    }
1500
1501    /// Sets the primary key's key flags.
1502    ///
1503    /// By default, the primary key is set to only be certification
1504    /// capable.  This allows the caller to set additional flags.
1505    ///
1506    /// # Examples
1507    ///
1508    /// Makes the primary key signing-capable but not
1509    /// certification-capable.
1510    ///
1511    /// ```
1512    /// use sequoia_openpgp as openpgp;
1513    /// # use openpgp::Result;
1514    /// use openpgp::cert::prelude::*;
1515    /// use openpgp::policy::StandardPolicy;
1516    /// use openpgp::types::KeyFlags;
1517    ///
1518    /// # fn main() -> Result<()> {
1519    /// let p = &StandardPolicy::new();
1520    ///
1521    /// let (cert, rev) =
1522    ///     CertBuilder::general_purpose(Some("Alice Lovelace <alice@example.org>"))
1523    ///         .set_primary_key_flags(KeyFlags::empty().set_signing())
1524    ///         .generate()?;
1525    ///
1526    /// // Observe that the primary key's certification capability is
1527    /// // set implicitly.
1528    /// assert_eq!(cert.with_policy(p, None)?.primary_key().key_flags(),
1529    ///            Some(KeyFlags::empty().set_signing()));
1530    /// # Ok(()) }
1531    /// ```
1532    pub fn set_primary_key_flags(mut self, flags: KeyFlags) -> Self {
1533        self.primary.flags = flags;
1534        self
1535    }
1536
1537    /// Sets a password to encrypt the secret keys with.
1538    ///
1539    /// The password is used to encrypt all secret key material.
1540    ///
1541    /// # Examples
1542    ///
1543    /// ```
1544    /// use sequoia_openpgp as openpgp;
1545    /// # use openpgp::Result;
1546    /// use openpgp::cert::prelude::*;
1547    ///
1548    /// # fn main() -> Result<()> {
1549    /// // Make the certificate expire in 10 minutes.
1550    /// let (cert, rev) =
1551    ///     CertBuilder::general_purpose(Some("Alice Lovelace <alice@example.org>"))
1552    ///         .set_password(Some("1234".into()))
1553    ///         .generate()?;
1554    ///
1555    /// for ka in cert.keys() {
1556    ///     assert!(ka.key().has_secret());
1557    /// }
1558    /// # Ok(()) }
1559    /// ```
1560    pub fn set_password(mut self, password: Option<Password>) -> Self {
1561        self.password = password;
1562        self
1563    }
1564
1565    /// Sets the certificate's validity period.
1566    ///
1567    /// The determines how long the certificate is valid.  That is,
1568    /// after the validity period, the certificate is considered to be
1569    /// expired.
1570    ///
1571    /// The validity period starts with the creation time (see
1572    /// [`CertBuilder::set_creation_time`]).
1573    ///
1574    /// A value of `None` means that the certificate never expires.
1575    ///
1576    /// See [this section](CertBuilder#expiration) of the type's
1577    /// documentation for security considerations of key expiration.
1578    ///
1579    /// # Examples
1580    ///
1581    /// ```
1582    /// use sequoia_openpgp as openpgp;
1583    /// # use openpgp::Result;
1584    /// use openpgp::cert::prelude::*;
1585    /// use openpgp::policy::StandardPolicy;
1586    /// use openpgp::types::RevocationKey;
1587    ///
1588    /// # fn main() -> Result<()> {
1589    /// let p = &StandardPolicy::new();
1590    ///
1591    /// let now = std::time::SystemTime::now();
1592    /// let s = std::time::Duration::new(1, 0);
1593    ///
1594    /// // Make the certificate expire in 10 minutes.
1595    /// let (cert,_) = CertBuilder::new()
1596    ///     .set_creation_time(now)
1597    ///     .set_validity_period(600 * s)
1598    ///     .generate()?;
1599    ///
1600    /// assert!(cert.with_policy(p, now)?.primary_key().alive().is_ok());
1601    /// assert!(cert.with_policy(p, now + 599 * s)?.primary_key().alive().is_ok());
1602    /// assert!(cert.with_policy(p, now + 600 * s)?.primary_key().alive().is_err());
1603    /// # Ok(()) }
1604    /// ```
1605    pub fn set_validity_period<T>(mut self, validity: T) -> Self
1606        where T: Into<Option<time::Duration>>
1607    {
1608        self.primary.validity = validity.into();
1609        self
1610    }
1611
1612    /// Sets designated revokers.
1613    ///
1614    /// Adds designated revokers to the primary key.  This allows the
1615    /// designated revoker to issue revocation certificates on behalf
1616    /// of the primary key.
1617    ///
1618    /// # Examples
1619    ///
1620    /// Make Alice a designated revoker for Bob:
1621    ///
1622    /// ```
1623    /// use sequoia_openpgp as openpgp;
1624    /// # use openpgp::Result;
1625    /// use openpgp::cert::prelude::*;
1626    /// use openpgp::policy::StandardPolicy;
1627    /// use openpgp::types::RevocationKey;
1628    ///
1629    /// # fn main() -> Result<()> {
1630    /// let p = &StandardPolicy::new();
1631    ///
1632    /// let (alice, _) =
1633    ///     CertBuilder::general_purpose(Some("alice@example.org"))
1634    ///         .generate()?;
1635    /// let (bob, _) =
1636    ///     CertBuilder::general_purpose(Some("bob@example.org"))
1637    ///         .set_revocation_keys(vec![(&alice).into()])
1638    ///         .generate()?;
1639    ///
1640    /// // Make sure Alice is listed as a designated revoker for Bob.
1641    /// assert_eq!(bob.revocation_keys(p).collect::<Vec<&RevocationKey>>(),
1642    ///            vec![&(&alice).into()]);
1643    /// # Ok(()) }
1644    /// ```
1645    pub fn set_revocation_keys(mut self, revocation_keys: Vec<RevocationKey>)
1646        -> Self
1647    {
1648        self.revocation_keys = Some(revocation_keys);
1649        self
1650    }
1651
1652    /// Set the algorithm used for encryption.
1653    ///
1654    /// This is a separate, higher-priority parameter from the [cipher
1655    /// suite](CertBuilder::set_cipher_suite) parameter.  When
1656    /// generating a key that will be used for signing (certification,
1657    /// data signing or authentication), this parameter is first
1658    /// considered.  If it is unset, then the algorithm selection
1659    /// falls back to using the cipher suite parameter.  Note: if the
1660    /// key flags indicate that the key should be used for both
1661    /// signing and encryption, then we also fall back to the cipher
1662    /// suite parameter.
1663    ///
1664    /// ```
1665    /// use sequoia_openpgp as openpgp;
1666    /// # use openpgp::Result;
1667    /// use openpgp::cert::prelude::*;
1668    /// # use openpgp::policy::StandardPolicy;
1669    /// # use openpgp::types::PublicKeyAlgorithm;
1670    /// use openpgp::types::PublicKeyAlgorithmSpecification;
1671    ///
1672    /// # fn main() -> Result<()> {
1673    /// # let p = &StandardPolicy::new();
1674    /// let (alice, _) =
1675    ///     CertBuilder::general_purpose(Some("alice@example.org"))
1676    ///         .set_encryption_algorithm(PublicKeyAlgorithmSpecification::rsa(4096))
1677    ///         .generate()?;
1678    /// # alice
1679    /// #   .with_policy(p, None).expect("valid cert")
1680    /// #   .keys()
1681    /// #   .for_transport_encryption()
1682    /// #   .for_storage_encryption()
1683    /// #   .for_each(|k| assert_eq!(k.key().pk_algo(),
1684    /// #             PublicKeyAlgorithm::RSAEncryptSign));
1685    /// # Ok(()) }
1686    /// ```
1687    pub fn set_encryption_algorithm(
1688        mut self, spec: PublicKeyAlgorithmSpecification)
1689        -> Self
1690    {
1691        self.for_encryption = Some(spec);
1692        self
1693    }
1694
1695    /// Set the algorithm used for signing.
1696    ///
1697    /// This is a separate, higher-priority parameter from the [cipher
1698    /// suite](CertBuilder::set_cipher_suite) parameter.  When
1699    /// generating a key that will be used for signing (certification,
1700    /// data signing or authentication), this parameter is first
1701    /// considered.  If it is unset, then the algorithm selection
1702    /// falls back to using the cipher suite parameter.  Note: if the
1703    /// key flags indicate that the key should be used for both
1704    /// signing and encryption, then we also fall back to the cipher
1705    /// suite parameter.
1706    ///
1707    /// ```
1708    /// use sequoia_openpgp as openpgp;
1709    /// # use openpgp::Result;
1710    /// use openpgp::cert::prelude::*;
1711    /// # use openpgp::policy::StandardPolicy;
1712    /// # use openpgp::types::PublicKeyAlgorithm;
1713    /// use openpgp::types::PublicKeyAlgorithmSpecification;
1714    ///
1715    /// # fn main() -> Result<()> {
1716    /// # let p = &StandardPolicy::new();
1717    /// let (alice, _) =
1718    ///     CertBuilder::general_purpose(Some("alice@example.org"))
1719    ///         .set_signing_algorithm(PublicKeyAlgorithmSpecification::rsa(4096))
1720    ///         .generate()?;
1721    /// # alice
1722    /// #   .with_policy(p, None).expect("valid cert")
1723    /// #   .keys()
1724    /// #   .for_signing()
1725    /// #   .for_certification()
1726    /// #   .for_authentication()
1727    /// #   .for_each(|k| assert_eq!(k.key().pk_algo(),
1728    /// #             PublicKeyAlgorithm::RSAEncryptSign));
1729    /// # Ok(()) }
1730    /// ```
1731    pub fn set_signing_algorithm(
1732        mut self, spec: PublicKeyAlgorithmSpecification)
1733        -> Self
1734    {
1735        self.for_signing = Some(spec);
1736        self
1737    }
1738
1739    /// Generates a certificate.
1740    ///
1741    /// # Examples
1742    ///
1743    /// ```
1744    /// use sequoia_openpgp as openpgp;
1745    /// # use openpgp::Result;
1746    /// use openpgp::cert::prelude::*;
1747    /// use openpgp::policy::StandardPolicy;
1748    /// use openpgp::types::RevocationKey;
1749    ///
1750    /// # fn main() -> Result<()> {
1751    /// let p = &StandardPolicy::new();
1752    ///
1753    /// let (alice, _) =
1754    ///     CertBuilder::general_purpose(Some("alice@example.org"))
1755    ///         .generate()?;
1756    /// # Ok(()) }
1757    /// ```
1758    pub fn generate(mut self) -> Result<(Cert, Signature)> {
1759        use crate::Packet;
1760        use crate::types::ReasonForRevocation;
1761
1762        let creation_time =
1763            self.creation_time.unwrap_or_else(|| {
1764                use crate::packet::signature::SIG_BACKDATE_BY;
1765                crate::now() -
1766                    time::Duration::new(SIG_BACKDATE_BY, 0)
1767            });
1768
1769        // Generate & self-sign primary key.
1770        let (primary, sig, mut signer) = self.primary_key(creation_time)?;
1771
1772        // Construct a skeleton cert.  We need this to bind the new
1773        // components to.
1774        let cert = Cert::try_from(vec![
1775            Packet::SecretKey({
1776                let mut primary = primary.clone();
1777                if let Some(ref password) = self.password {
1778                    let (k, mut secret) = primary.take_secret();
1779                    secret.encrypt_in_place(&k, password)?;
1780                    primary = k.add_secret(secret).0;
1781                }
1782                primary
1783            }),
1784        ])?;
1785        // We will, however, collect any signatures and components in
1786        // a separate vector, and only add them in the end, so that we
1787        // canonicalize the new certificate just once.
1788        let mut acc = vec![
1789            Packet::from(sig),
1790        ];
1791
1792        // We want to mark exactly one User ID or Attribute as primary.
1793        // First, figure out whether one of the binding signature
1794        // templates have the primary flag set.
1795        let have_primary_user_thing = {
1796            let is_primary = |osig: &Option<SignatureBuilder>| -> bool {
1797                osig.as_ref().and_then(|s| s.primary_userid()).unwrap_or(false)
1798            };
1799
1800            self.userids.iter().map(|(s, _)| s).any(is_primary)
1801                || self.user_attributes.iter().map(|(s, _)| s).any(is_primary)
1802        };
1803        let mut emitted_primary_user_thing = false;
1804
1805        // Sign UserIDs.
1806        for (template, uid) in std::mem::take(&mut self.userids).into_iter() {
1807            let sig = template.unwrap_or_else(
1808                || SignatureBuilder::new(SignatureType::PositiveCertification));
1809            let sig = Self::signature_common(sig, creation_time,
1810                                             self.exportable)?;
1811            let mut sig = self.add_primary_key_metadata(sig)?;
1812
1813            // Make sure we mark exactly one User ID or Attribute as
1814            // primary.
1815            if emitted_primary_user_thing {
1816                sig = sig.modify_hashed_area(|mut a| {
1817                    a.remove_all(SubpacketTag::PrimaryUserID);
1818                    Ok(a)
1819                })?;
1820            } else if have_primary_user_thing {
1821                // Check if this is the first explicitly selected
1822                // user thing.
1823                emitted_primary_user_thing |=
1824                    sig.primary_userid().unwrap_or(false);
1825            } else {
1826                // Implicitly mark the first as primary.
1827                sig = sig.set_primary_userid(true)?;
1828                emitted_primary_user_thing = true;
1829            }
1830
1831            let signature = uid.bind(&mut signer, &cert, sig)?;
1832            acc.push(uid.into());
1833            acc.push(signature.into());
1834        }
1835
1836        // Sign UserAttributes.
1837        for (template, ua) in std::mem::take(&mut self.user_attributes) {
1838            let sig = template.unwrap_or_else(
1839                || SignatureBuilder::new(SignatureType::PositiveCertification));
1840            let sig = Self::signature_common(
1841                sig, creation_time, self.exportable)?;
1842            let mut sig = self.add_primary_key_metadata(sig)?;
1843
1844            // Make sure we mark exactly one User ID or Attribute as
1845            // primary.
1846            if emitted_primary_user_thing {
1847                sig = sig.modify_hashed_area(|mut a| {
1848                    a.remove_all(SubpacketTag::PrimaryUserID);
1849                    Ok(a)
1850                })?;
1851            } else if have_primary_user_thing {
1852                // Check if this is the first explicitly selected
1853                // user thing.
1854                emitted_primary_user_thing |=
1855                    sig.primary_userid().unwrap_or(false);
1856            } else {
1857                // Implicitly mark the first as primary.
1858                sig = sig.set_primary_userid(true)?;
1859                emitted_primary_user_thing = true;
1860            }
1861
1862            let signature = ua.bind(&mut signer, &cert, sig)?;
1863            acc.push(ua.into());
1864            acc.push(signature.into());
1865        }
1866
1867        // Sign subkeys.
1868        for (template, blueprint) in self.subkeys {
1869            let flags = &blueprint.flags;
1870
1871            let for_signing = flags.for_signing()
1872                || flags.for_certification()
1873                || flags.for_authentication();
1874            let for_encryption = flags.for_transport_encryption()
1875                || flags.for_storage_encryption();
1876
1877            let subkey = match (for_signing, for_encryption) {
1878                (true, false) => if let Some(spec) = blueprint.for_signing {
1879                    spec.generate_key_for(self.profile, flags)?
1880                } else if let Some(ciphersuite) = blueprint.ciphersuite {
1881                    ciphersuite.generate_key(flags, self.profile)?
1882                } else if let Some(ref spec) = self.for_signing {
1883                    spec.generate_key_for(self.profile, flags)?
1884                } else {
1885                    self.ciphersuite.generate_key(flags, self.profile)?
1886                },
1887                (false, true) => if let Some(spec) = blueprint.for_encryption {
1888                    spec.generate_key_for(self.profile, flags)?
1889                } else if let Some(ciphersuite) = blueprint.ciphersuite {
1890                    ciphersuite.generate_key(flags, self.profile)?
1891                } else if let Some(ref spec) = self.for_encryption {
1892                    spec.generate_key_for(self.profile, flags)?
1893                } else {
1894                    self.ciphersuite.generate_key(flags, self.profile)?
1895                },
1896                (_, _) => {
1897                    // Either the key should be used for encryption
1898                    // and signing or neither.  In either case, fall
1899                    // back to the ciphersuite parameter.
1900                    blueprint.ciphersuite
1901                        .unwrap_or(self.ciphersuite)
1902                        .generate_key(flags, self.profile)?
1903                }
1904            };
1905
1906            let mut subkey = subkey.role_into_subordinate();
1907            subkey.set_creation_time(creation_time)?;
1908
1909            let sig = template.unwrap_or_else(
1910                || SignatureBuilder::new(SignatureType::SubkeyBinding));
1911            let sig = Self::signature_common(
1912                sig, creation_time, self.exportable)?;
1913            let mut builder = sig
1914                .set_key_flags(flags.clone())?
1915                .set_key_validity_period(blueprint.validity.or(self.primary.validity))?;
1916
1917            if flags.for_certification() || flags.for_signing()
1918                || flags.for_authentication()
1919            {
1920                // We need to create a primary key binding signature.
1921                let mut subkey_signer = subkey.clone().into_keypair().unwrap();
1922                let backsig =
1923                    signature::SignatureBuilder::new(SignatureType::PrimaryKeyBinding)
1924                    .set_signature_creation_time(creation_time)?
1925                    // GnuPG wants at least a 512-bit hash for P521 keys.
1926                    .set_hash_algo(HashAlgorithm::SHA512)
1927                    .sign_primary_key_binding(&mut subkey_signer, &primary,
1928                                              &subkey)?;
1929                builder = builder.set_embedded_signature(backsig)?;
1930            }
1931
1932            let signature = subkey.bind(&mut signer, &cert, builder)?;
1933
1934            if let Some(ref password) = self.password {
1935                let (k, mut secret) = subkey.take_secret();
1936                secret.encrypt_in_place(&k, password)?;
1937                subkey = k.add_secret(secret).0;
1938            }
1939            acc.push(subkey.into());
1940            acc.push(signature.into());
1941        }
1942
1943        // Now add the new components and canonicalize once.
1944        let cert = cert.insert_packets(acc)?.0;
1945
1946        let revocation = CertRevocationBuilder::new()
1947            .set_signature_creation_time(creation_time)?
1948            .set_reason_for_revocation(
1949                ReasonForRevocation::Unspecified, b"Unspecified")?
1950            .build(&mut signer, &cert, None)?;
1951
1952        // keys generated by the builder are never invalid
1953        assert!(cert.bad.is_empty());
1954        assert!(cert.unknowns.is_empty());
1955
1956        Ok((cert, revocation))
1957    }
1958
1959    /// Creates the primary key and a direct key signature.
1960    fn primary_key(&self, creation_time: std::time::SystemTime)
1961        -> Result<(KeySecretKey, Signature, Box<dyn Signer>)>
1962    {
1963        let key_flags = KeyFlags::empty().set_certification();
1964        let key = if let Some(algo) = self.primary.for_signing.as_ref() {
1965            algo.generate_key_for(self.profile, key_flags)?
1966        } else if let Some(ciphersuite) = self.primary.ciphersuite {
1967            ciphersuite.generate_key(key_flags, self.profile)?
1968        } else if let Some(algo) = self.for_signing.as_ref() {
1969            algo.generate_key_for(self.profile, key_flags)?
1970        } else {
1971            self.ciphersuite.generate_key(key_flags, self.profile)?
1972        };
1973        let mut key = key.role_into_primary();
1974        key.set_creation_time(creation_time)?;
1975        let sig = SignatureBuilder::new(SignatureType::DirectKey);
1976        let sig = Self::signature_common(
1977            sig, creation_time, self.exportable)?;
1978        let mut sig = self.add_primary_key_metadata(sig)?;
1979
1980        if let Some(ref revocation_keys) = self.revocation_keys {
1981            for k in revocation_keys.into_iter().cloned() {
1982                sig = sig.add_revocation_key(k)?;
1983            }
1984        }
1985
1986        let mut signer = key.clone().into_keypair()
1987            .expect("key generated above has a secret");
1988        let sig = sig.sign_direct_key(&mut signer, key.parts_as_public())?;
1989
1990        Ok((key, sig, Box::new(signer)))
1991    }
1992
1993    /// Common settings for generated signatures.
1994    fn signature_common(builder: SignatureBuilder,
1995                        creation_time: time::SystemTime,
1996                        exportable: bool)
1997                        -> Result<SignatureBuilder>
1998    {
1999        let mut builder = builder
2000            // GnuPG wants at least a 512-bit hash for P521 keys.
2001            .set_hash_algo(HashAlgorithm::SHA512)
2002            .set_signature_creation_time(creation_time)?;
2003        if ! exportable {
2004            builder = builder.set_exportable_certification(false)?;
2005        }
2006        Ok(builder)
2007    }
2008
2009
2010    /// Adds primary key metadata to the signature.
2011    fn add_primary_key_metadata(&self,
2012                                builder: SignatureBuilder)
2013                                -> Result<SignatureBuilder>
2014    {
2015        builder
2016            .set_features(self.features.clone())?
2017            .set_key_flags(self.primary.flags.clone())?
2018            .set_key_validity_period(self.primary.validity)?
2019            .set_preferred_hash_algorithms(vec![
2020                HashAlgorithm::SHA512,
2021                HashAlgorithm::SHA256,
2022            ])?
2023            .set_preferred_symmetric_algorithms(vec![
2024                SymmetricAlgorithm::AES256,
2025                SymmetricAlgorithm::AES128,
2026            ])
2027    }
2028}
2029
2030#[cfg(test)]
2031mod tests {
2032    use std::str::FromStr;
2033
2034    use super::*;
2035    use crate::Fingerprint;
2036    use crate::crypto::mpi::PublicKey;
2037    use crate::packet::signature::subpacket::{SubpacketTag, SubpacketValue};
2038    use crate::types::Curve;
2039    use crate::types::PublicKeyAlgorithm;
2040    use crate::parse::Parse;
2041    use crate::policy::StandardPolicy as P;
2042    use crate::serialize::Serialize;
2043    use crate::types::PublicKeyAlgorithmSpecification;
2044
2045    #[test]
2046    fn all_opts() {
2047        let p = &P::new();
2048
2049        let (cert, _) = CertBuilder::new()
2050            .set_cipher_suite(CipherSuite::Cv25519)
2051            .add_userid("test1@example.com")
2052            .add_userid("test2@example.com")
2053            .add_signing_subkey()
2054            .add_transport_encryption_subkey()
2055            .add_certification_subkey()
2056            .generate().unwrap();
2057
2058        let mut userids = cert.userids().with_policy(p, None)
2059            .map(|u| String::from_utf8_lossy(u.userid().value()).into_owned())
2060            .collect::<Vec<String>>();
2061        userids.sort();
2062
2063        assert_eq!(userids,
2064                   &[ "test1@example.com",
2065                      "test2@example.com",
2066                   ][..]);
2067        assert_eq!(cert.subkeys().count(), 3);
2068    }
2069
2070    #[test]
2071    fn direct_key_sig() {
2072        let p = &P::new();
2073
2074        let (cert, _) = CertBuilder::new()
2075            .set_cipher_suite(CipherSuite::Cv25519)
2076            .add_signing_subkey()
2077            .add_transport_encryption_subkey()
2078            .add_certification_subkey()
2079            .generate().unwrap();
2080
2081        assert_eq!(cert.userids().count(), 0);
2082        assert_eq!(cert.subkeys().count(), 3);
2083        let sig =
2084            cert.primary_key().with_policy(p, None).unwrap().binding_signature();
2085        assert_eq!(sig.typ(), crate::types::SignatureType::DirectKey);
2086        assert!(sig.features().unwrap().supports_seipdv1());
2087    }
2088
2089    #[test]
2090    fn setter() {
2091        let (cert1, _) = CertBuilder::new()
2092            .set_cipher_suite(CipherSuite::Cv25519)
2093            .set_cipher_suite(CipherSuite::RSA3k)
2094            .set_cipher_suite(CipherSuite::Cv25519)
2095            .generate().unwrap();
2096        assert_eq!(cert1.primary_key().key().pk_algo(), PublicKeyAlgorithm::EdDSA);
2097
2098        let (cert2, _) = CertBuilder::new()
2099            .set_cipher_suite(CipherSuite::RSA3k)
2100            .add_userid("test2@example.com")
2101            .add_transport_encryption_subkey()
2102            .generate().unwrap();
2103        assert_eq!(cert2.primary_key().key().pk_algo(),
2104                   PublicKeyAlgorithm::RSAEncryptSign);
2105        assert_eq!(cert2.subkeys().next().unwrap().key().pk_algo(),
2106                   PublicKeyAlgorithm::RSAEncryptSign);
2107    }
2108
2109    #[test]
2110    fn defaults() {
2111        let p = &P::new();
2112        let (cert1, _) = CertBuilder::new()
2113            .add_userid("test2@example.com")
2114            .generate().unwrap();
2115        assert_eq!(cert1.primary_key().key().pk_algo(),
2116                   PublicKeyAlgorithm::EdDSA);
2117        assert!(cert1.subkeys().next().is_none());
2118        assert!(cert1.with_policy(p, None).unwrap().primary_userid().unwrap()
2119                .binding_signature().features().unwrap().supports_seipdv1());
2120    }
2121
2122    #[test]
2123    fn not_always_certify() {
2124        let p = &P::new();
2125        let (cert1, _) = CertBuilder::new()
2126            .set_cipher_suite(CipherSuite::Cv25519)
2127            .set_primary_key_flags(KeyFlags::empty())
2128            .add_transport_encryption_subkey()
2129            .generate().unwrap();
2130        assert!(! cert1.primary_key().with_policy(p, None).unwrap().for_certification());
2131        assert_eq!(cert1.keys().subkeys().count(), 1);
2132    }
2133
2134    #[test]
2135    fn gen_wired_subkeys() {
2136        let (cert1, _) = CertBuilder::new()
2137            .set_cipher_suite(CipherSuite::Cv25519)
2138            .set_primary_key_flags(KeyFlags::empty())
2139            .add_subkey(KeyFlags::empty().set_certification(), None, None)
2140            .generate().unwrap();
2141        let sig_pkts = cert1.subkeys().next().unwrap().bundle()
2142            .self_signatures().next().unwrap().hashed_area();
2143
2144        match sig_pkts.subpacket(SubpacketTag::KeyFlags).unwrap().value() {
2145            SubpacketValue::KeyFlags(ref ks) => assert!(ks.for_certification()),
2146            v => panic!("Unexpected subpacket: {:?}", v),
2147        }
2148
2149        assert_eq!(cert1.subkeys().count(), 1);
2150    }
2151
2152    #[test]
2153    fn generate_revocation_certificate() {
2154        let p = &P::new();
2155        use crate::types::RevocationStatus;
2156        let (cert, revocation) = CertBuilder::new()
2157            .set_cipher_suite(CipherSuite::Cv25519)
2158            .generate().unwrap();
2159        assert_eq!(cert.revocation_status(p, None),
2160                   RevocationStatus::NotAsFarAsWeKnow);
2161
2162        let cert = cert.insert_packets(revocation.clone()).unwrap().0;
2163        assert_eq!(cert.revocation_status(p, None),
2164                   RevocationStatus::Revoked(vec![ &revocation ]));
2165    }
2166
2167    #[test]
2168    fn builder_roundtrip() {
2169        use std::convert::TryFrom;
2170
2171        let (cert,_) = CertBuilder::new()
2172            .set_cipher_suite(CipherSuite::Cv25519)
2173            .add_signing_subkey()
2174            .generate().unwrap();
2175        let pile = cert.clone().into_packet_pile().into_children().collect::<Vec<_>>();
2176        let exp = Cert::try_from(pile).unwrap();
2177
2178        assert_eq!(cert, exp);
2179    }
2180
2181    #[test]
2182    fn encrypted_secrets() {
2183        let (cert,_) = CertBuilder::new()
2184            .set_cipher_suite(CipherSuite::Cv25519)
2185            .set_password(Some(String::from("streng geheim").into()))
2186            .generate().unwrap();
2187        assert!(cert.primary_key().key().optional_secret().unwrap().is_encrypted());
2188    }
2189
2190    #[test]
2191    fn all_ciphersuites() {
2192        for cs in CipherSuite::variants()
2193            .into_iter().filter(|cs| cs.is_supported().is_ok())
2194        {
2195            CertBuilder::new()
2196                .set_profile(crate::Profile::RFC9580).unwrap()
2197                .set_cipher_suite(cs)
2198                .add_transport_encryption_subkey()
2199                .generate()
2200                .unwrap();
2201        }
2202    }
2203
2204    #[test]
2205    fn validity_periods() {
2206        let p = &P::new();
2207
2208        let now = crate::now();
2209        let s = std::time::Duration::new(1, 0);
2210
2211        let (cert,_) = CertBuilder::new()
2212            .set_creation_time(now)
2213            .set_validity_period(600 * s)
2214            .add_subkey(KeyFlags::empty().set_signing(),
2215                        300 * s, None)
2216            .add_subkey(KeyFlags::empty().set_authentication(),
2217                        None, None)
2218            .generate().unwrap();
2219
2220        let key = cert.primary_key().key();
2221        let sig = &cert.primary_key().bundle().self_signatures().next().unwrap();
2222        assert!(sig.key_alive(key, now).is_ok());
2223        assert!(sig.key_alive(key, now + 590 * s).is_ok());
2224        assert!(! sig.key_alive(key, now + 610 * s).is_ok());
2225
2226        let ka = cert.keys().with_policy(p, now).alive().revoked(false)
2227            .for_signing().next().unwrap();
2228        assert!(ka.alive().is_ok());
2229        assert!(ka.clone().with_policy(p, now + 290 * s).unwrap().alive().is_ok());
2230        assert!(! ka.clone().with_policy(p, now + 310 * s).unwrap().alive().is_ok());
2231
2232        let ka = cert.keys().with_policy(p, now).alive().revoked(false)
2233            .for_authentication().next().unwrap();
2234        assert!(ka.alive().is_ok());
2235        assert!(ka.clone().with_policy(p, now + 590 * s).unwrap().alive().is_ok());
2236        assert!(! ka.clone().with_policy(p, now + 610 * s).unwrap().alive().is_ok());
2237    }
2238
2239    #[test]
2240    fn creation_time() {
2241        let p = &P::new();
2242
2243        use std::time::UNIX_EPOCH;
2244        let (cert, rev) = CertBuilder::new()
2245            .set_creation_time(UNIX_EPOCH)
2246            .set_cipher_suite(CipherSuite::Cv25519)
2247            .add_userid("foo")
2248            .add_signing_subkey()
2249            .generate().unwrap();
2250
2251        assert_eq!(cert.primary_key().key().creation_time(), UNIX_EPOCH);
2252        assert_eq!(cert.primary_key().with_policy(p, None).unwrap()
2253                   .binding_signature()
2254                   .signature_creation_time().unwrap(), UNIX_EPOCH);
2255        assert_eq!(cert.primary_key().with_policy(p, None).unwrap()
2256                   .direct_key_signature().unwrap()
2257                   .signature_creation_time().unwrap(), UNIX_EPOCH);
2258        assert_eq!(rev.signature_creation_time().unwrap(), UNIX_EPOCH);
2259
2260        // (Sub)Keys.
2261        assert_eq!(cert.keys().with_policy(p, None).count(), 2);
2262        for ka in cert.keys().with_policy(p, None) {
2263            assert_eq!(ka.key().creation_time(), UNIX_EPOCH);
2264            assert_eq!(ka.binding_signature()
2265                       .signature_creation_time().unwrap(), UNIX_EPOCH);
2266        }
2267
2268        // UserIDs.
2269        assert_eq!(cert.userids().count(), 1);
2270        for ui in cert.userids().with_policy(p, None) {
2271            assert_eq!(ui.binding_signature()
2272                       .signature_creation_time().unwrap(), UNIX_EPOCH);
2273        }
2274    }
2275
2276    #[test]
2277    fn designated_revokers() -> Result<()> {
2278        use std::collections::HashSet;
2279
2280        let p = &P::new();
2281
2282        let fpr1 = "C03F A641 1B03 AE12 5764  6118 7223 B566 78E0 2528";
2283        let fpr2 = "50E6 D924 308D BF22 3CFB  510A C2B8 1905 6C65 2598";
2284        let revokers = vec![
2285            RevocationKey::new(PublicKeyAlgorithm::RSAEncryptSign,
2286                               Fingerprint::from_str(fpr1)?,
2287                               false),
2288            RevocationKey::new(PublicKeyAlgorithm::ECDSA,
2289                               Fingerprint::from_str(fpr2)?,
2290                               false)
2291        ];
2292
2293        let (cert,_)
2294            = CertBuilder::general_purpose(Some("alice@example.org"))
2295            .set_revocation_keys(revokers.clone())
2296            .generate()?;
2297        let cert = cert.with_policy(p, None)?;
2298
2299        assert_eq!(cert.revocation_keys().collect::<HashSet<_>>(),
2300                   revokers.iter().collect::<HashSet<_>>());
2301
2302        // Do it again, with a key that has no User IDs.
2303        let (cert,_) = CertBuilder::new()
2304            .set_revocation_keys(revokers.clone())
2305            .generate()?;
2306        let cert = cert.with_policy(p, None)?;
2307        assert!(cert.primary_userid().is_err());
2308
2309        assert_eq!(cert.revocation_keys().collect::<HashSet<_>>(),
2310                   revokers.iter().collect::<HashSet<_>>());
2311
2312        // The designated revokers on all signatures should be
2313        // considered.
2314        let now = crate::types::Timestamp::now();
2315        let then = now.checked_add(crate::types::Duration::days(1)?).unwrap();
2316        let (cert,_) = CertBuilder::new()
2317            .set_revocation_keys(revokers.clone())
2318            .set_creation_time(now)
2319            .generate()?;
2320
2321        // Add a newer direct key signature.
2322        use crate::crypto::hash::Hash;
2323        let mut primary_signer =
2324            cert.primary_key().key().clone().parts_into_secret()?
2325            .into_keypair()?;
2326        let mut hash = HashAlgorithm::SHA512.context()?
2327            .for_signature(primary_signer.public().version());
2328        cert.primary_key().key().hash(&mut hash)?;
2329        let sig = signature::SignatureBuilder::new(SignatureType::DirectKey)
2330            .set_signature_creation_time(then)?
2331            .sign_hash(&mut primary_signer, hash)?;
2332        let cert = cert.insert_packets(sig)?.0;
2333
2334        assert!(cert.with_policy(p, then)?.primary_userid().is_err());
2335        assert_eq!(cert.revocation_keys(p).collect::<HashSet<_>>(),
2336                   revokers.iter().collect::<HashSet<_>>());
2337        Ok(())
2338    }
2339
2340    /// Checks that the builder emits exactly one user id or attribute
2341    /// marked as primary.
2342    #[test]
2343    fn primary_user_things() -> Result<()> {
2344        fn count_primary_user_things(c: Cert) -> usize {
2345            c.into_packets().map(|p| match p {
2346                Packet::Signature(s) if s.primary_userid().unwrap_or(false)
2347                    => 1,
2348                _ => 0,
2349            }).sum()
2350        }
2351
2352        use crate::packet::{prelude::*, user_attribute::Subpacket};
2353        let ua_foo =
2354            UserAttribute::new(&[Subpacket::Unknown(7, vec![7; 7].into())])?;
2355        let ua_bar =
2356            UserAttribute::new(&[Subpacket::Unknown(11, vec![11; 11].into())])?;
2357
2358        let p = &P::new();
2359        let positive = SignatureType::PositiveCertification;
2360
2361        let (c, _) = CertBuilder::new().generate()?;
2362        assert_eq!(count_primary_user_things(c), 0);
2363
2364        let (c, _) = CertBuilder::new()
2365            .add_userid("foo")
2366            .generate()?;
2367        assert_eq!(count_primary_user_things(c), 1);
2368
2369        let (c, _) = CertBuilder::new()
2370            .add_userid("foo")
2371            .add_userid("bar")
2372            .generate()?;
2373        assert_eq!(count_primary_user_things(c), 1);
2374
2375        let (c, _) = CertBuilder::new()
2376            .add_user_attribute(ua_foo.clone())
2377            .generate()?;
2378        assert_eq!(count_primary_user_things(c), 1);
2379
2380        let (c, _) = CertBuilder::new()
2381            .add_user_attribute(ua_foo.clone())
2382            .add_user_attribute(ua_bar.clone())
2383            .generate()?;
2384        assert_eq!(count_primary_user_things(c), 1);
2385
2386        let (c, _) = CertBuilder::new()
2387            .add_userid("foo")
2388            .add_user_attribute(ua_foo.clone())
2389            .generate()?;
2390        let vc = c.with_policy(p, None)?;
2391        assert_eq!(vc.primary_userid()?.binding_signature().primary_userid(),
2392                   Some(true));
2393        assert_eq!(vc.primary_user_attribute()?.binding_signature().primary_userid(),
2394                   None);
2395        assert_eq!(count_primary_user_things(c), 1);
2396
2397        let (c, _) = CertBuilder::new()
2398            .add_user_attribute(ua_foo.clone())
2399            .add_userid("foo")
2400            .generate()?;
2401        let vc = c.with_policy(p, None)?;
2402        assert_eq!(vc.primary_userid()?.binding_signature().primary_userid(),
2403                   Some(true));
2404        assert_eq!(vc.primary_user_attribute()?.binding_signature().primary_userid(),
2405                   None);
2406        assert_eq!(count_primary_user_things(c), 1);
2407
2408        let (c, _) = CertBuilder::new()
2409            .add_userid("foo")
2410            .add_userid_with(
2411                "buz",
2412                SignatureBuilder::new(positive).set_primary_userid(false)?)?
2413            .add_userid_with(
2414                "bar",
2415                SignatureBuilder::new(positive).set_primary_userid(true)?)?
2416            .add_userid_with(
2417                "baz",
2418                SignatureBuilder::new(positive).set_primary_userid(true)?)?
2419            .generate()?;
2420        let vc = c.with_policy(p, None)?;
2421        assert_eq!(vc.primary_userid()?.userid().value(), b"bar");
2422        assert_eq!(count_primary_user_things(c), 1);
2423
2424        Ok(())
2425    }
2426
2427    #[test]
2428    fn non_exportable_cert() -> Result<()> {
2429        // Make sure that when we export a non-exportable cert,
2430        // nothing is exported.
2431
2432        let (cert, _) =
2433            CertBuilder::general_purpose(Some("alice@example.org"))
2434            .set_exportable(false)
2435            .generate()?;
2436
2437        let (bob, _) =
2438            CertBuilder::general_purpose(Some("bob@example.org"))
2439            .generate()?;
2440
2441        // Have Bob certify Alice's primary User ID with an exportable
2442        // signature.  This shouldn't make Alice's certificate
2443        // exportable.
2444        let mut keypair = bob.primary_key().key().clone()
2445            .parts_into_secret()?.into_keypair()?;
2446        let certification = cert.userids().nth(0).unwrap()
2447            .userid()
2448            .certify(&mut keypair, &cert,
2449                     SignatureType::PositiveCertification,
2450                     None, None)?;
2451        let cert = cert.insert_packets(certification)?.0;
2452
2453        macro_rules! check {
2454            ($cert: expr, $export: ident, $expected: expr) => {
2455                let mut exported = Vec::new();
2456                $cert.$export(&mut exported)?;
2457
2458                let certs = CertParser::from_bytes(&exported)?
2459                    .collect::<Result<Vec<Cert>>>()?;
2460
2461                assert_eq!(certs.len(), $expected);
2462
2463                if $expected == 0 {
2464                    assert_eq!(exported.len(), 0,
2465                               "{}", String::from_utf8_lossy(&exported));
2466                } else {
2467                    assert!(exported.len() > 0);
2468                }
2469            }
2470        }
2471
2472        // Binary cert:
2473        check!(cert, export, 0);
2474        check!(cert, serialize, 1);
2475
2476        // Binary TSK:
2477        check!(cert.as_tsk(), export, 0);
2478        check!(cert.as_tsk(), serialize, 1);
2479
2480        // Armored cert:
2481        check!(cert.armored(), export, 0);
2482        check!(cert.armored(), serialize, 1);
2483
2484        // Armored TSK:
2485        check!(cert.as_tsk().armored(), export, 0);
2486        check!(cert.as_tsk().armored(), serialize, 1);
2487
2488        // Have Alice add an exportable self signature.  Now her
2489        // certificate should be exportable.
2490        let mut keypair = cert.primary_key().key().clone()
2491            .parts_into_secret()?.into_keypair()?;
2492        let certification = cert.userids().nth(0).unwrap()
2493            .userid()
2494            .certify(&mut keypair, &cert,
2495                     SignatureType::PositiveCertification,
2496                     None, None)?;
2497        let cert = cert.insert_packets(certification)?.0;
2498
2499        macro_rules! check {
2500            ($cert: expr, $export: ident, $expected: expr) => {
2501                let mut exported = Vec::new();
2502                $cert.$export(&mut exported)?;
2503
2504                let certs = CertParser::from_bytes(&exported)?
2505                    .collect::<Result<Vec<Cert>>>()?;
2506
2507                assert_eq!(certs.len(), $expected);
2508
2509                if $expected == 0 {
2510                    assert_eq!(exported.len(), 0,
2511                               "{}", String::from_utf8_lossy(&exported));
2512                } else {
2513                    assert!(exported.len() > 0);
2514                }
2515            }
2516        }
2517
2518        // Binary cert:
2519        check!(cert, export, 1);
2520        check!(cert, serialize, 1);
2521
2522        // Binary TSK:
2523        check!(cert.as_tsk(), export, 1);
2524        check!(cert.as_tsk(), serialize, 1);
2525
2526        // Armored cert:
2527        check!(cert.armored(), export, 1);
2528        check!(cert.armored(), serialize, 1);
2529
2530        // Armored TSK:
2531        check!(cert.as_tsk().armored(), export, 1);
2532        check!(cert.as_tsk().armored(), serialize, 1);
2533
2534        Ok(())
2535    }
2536
2537    #[test]
2538    fn check_algos() {
2539        for (cipher_suite, profile, algos, curves) in [
2540            (CipherSuite::Cv25519,
2541             Profile::RFC4880,
2542             &[ PublicKeyAlgorithm::EdDSA, PublicKeyAlgorithm::ECDH ][..],
2543             &[ Curve::Ed25519, Curve::Cv25519, ][..]),
2544            (CipherSuite::Cv25519,
2545             Profile::RFC9580,
2546             &[ PublicKeyAlgorithm::Ed25519, PublicKeyAlgorithm::X25519 ],
2547             &[]),
2548
2549            (CipherSuite::Cv448,
2550             Profile::RFC4880,
2551             &[ PublicKeyAlgorithm::Ed448, PublicKeyAlgorithm::X448 ],
2552             &[]),
2553            (CipherSuite::Cv448,
2554             Profile::RFC9580,
2555             &[ PublicKeyAlgorithm::Ed448, PublicKeyAlgorithm::X448 ],
2556             &[]),
2557
2558            (CipherSuite::RSA2k,
2559             Profile::RFC4880,
2560             &[ PublicKeyAlgorithm::RSAEncryptSign ],
2561             &[]),
2562            (CipherSuite::RSA2k,
2563             Profile::RFC9580,
2564             &[ PublicKeyAlgorithm::RSAEncryptSign ],
2565             &[]),
2566
2567            (CipherSuite::RSA3k,
2568             Profile::RFC4880,
2569             &[ PublicKeyAlgorithm::RSAEncryptSign ],
2570             &[]),
2571            (CipherSuite::RSA3k,
2572             Profile::RFC9580,
2573             &[ PublicKeyAlgorithm::RSAEncryptSign ],
2574             &[]),
2575
2576            (CipherSuite::RSA4k,
2577             Profile::RFC4880,
2578             &[ PublicKeyAlgorithm::RSAEncryptSign ],
2579             &[]),
2580            (CipherSuite::RSA4k,
2581             Profile::RFC9580,
2582             &[ PublicKeyAlgorithm::RSAEncryptSign ],
2583             &[]),
2584
2585            (CipherSuite::P256,
2586             Profile::RFC4880,
2587             &[ PublicKeyAlgorithm::ECDSA, PublicKeyAlgorithm::ECDH ],
2588             &[ Curve::NistP256 ]),
2589            (CipherSuite::P256,
2590             Profile::RFC9580,
2591             &[ PublicKeyAlgorithm::ECDSA, PublicKeyAlgorithm::ECDH ],
2592             &[ Curve::NistP256 ]),
2593
2594            (CipherSuite::P384,
2595             Profile::RFC4880,
2596             &[ PublicKeyAlgorithm::ECDSA, PublicKeyAlgorithm::ECDH ],
2597             &[ Curve::NistP384 ]),
2598            (CipherSuite::P384,
2599             Profile::RFC9580,
2600             &[ PublicKeyAlgorithm::ECDSA, PublicKeyAlgorithm::ECDH ],
2601             &[ Curve::NistP384 ]),
2602
2603            (CipherSuite::P521,
2604             Profile::RFC4880,
2605             &[ PublicKeyAlgorithm::ECDSA, PublicKeyAlgorithm::ECDH ],
2606             &[ Curve::NistP521 ]),
2607            (CipherSuite::P521,
2608             Profile::RFC9580,
2609             &[ PublicKeyAlgorithm::ECDSA, PublicKeyAlgorithm::ECDH ],
2610             &[ Curve::NistP521 ]),
2611        ]
2612        {
2613            eprintln!("Testing that generating {:?}, {:?} results in \
2614                       algorithms: {}; curves: {}",
2615                      cipher_suite, profile,
2616                      algos
2617                          .iter()
2618                          .map(|a| a.to_string())
2619                          .collect::<Vec<_>>()
2620                          .join(", "),
2621                      if curves.is_empty() {
2622                          "none".to_string()
2623                      } else {
2624                          curves
2625                              .iter()
2626                              .map(|a| a.to_string())
2627                              .collect::<Vec<_>>()
2628                              .join(", ")
2629                      });
2630
2631            if let Err(err) = cipher_suite.is_supported() {
2632                eprintln!("Skipping, cipher suite is not supported: {}", err);
2633                continue;
2634            }
2635
2636            let (cert, _) = CertBuilder::general_purpose(Some("x@example.org"))
2637                .set_cipher_suite(cipher_suite)
2638                .set_profile(profile)
2639                .expect("Profile is supported")
2640                .generate()
2641                .expect("Cipher suite is supported");
2642
2643            let mut algos_got = cert.keys()
2644                .map(|ka| ka.key().pk_algo())
2645                .collect::<Vec<_>>();
2646            algos_got.sort();
2647            algos_got.dedup();
2648
2649            let mut algos_expected = algos.to_vec();
2650            algos_expected.sort();
2651
2652            assert_eq!(&algos_expected, &algos_got,
2653                       "\n\
2654                        algos expected: {}\n\
2655                        algos got:      {}",
2656                       algos_expected
2657                           .iter()
2658                           .map(|a| a.to_string())
2659                           .collect::<Vec<_>>()
2660                           .join(", "),
2661                       algos_got
2662                           .iter()
2663                           .map(|a| a.to_string())
2664                           .collect::<Vec<_>>()
2665                           .join(", "));
2666
2667
2668            let mut curves_got = cert.keys()
2669                .filter_map(|ka| match ka.key().mpis() {
2670                    PublicKey::EdDSA { curve, .. }
2671                    | PublicKey::ECDSA { curve, .. }
2672                    | PublicKey::ECDH { curve, .. } =>
2673                    {
2674                        Some(curve.clone())
2675                    }
2676                    _ => None,
2677                })
2678                .collect::<Vec<_>>();
2679            curves_got.sort();
2680            curves_got.dedup();
2681
2682            let mut curves_expected = curves.to_vec();
2683            curves_expected.sort();
2684
2685            assert_eq!(&curves_expected, &curves_got,
2686                       "\n\
2687                        curves expected: {}\n\
2688                        curves got:      {}",
2689                       if curves_expected.is_empty() {
2690                           "(none)".to_string()
2691                       } else {
2692                           curves_expected
2693                               .iter()
2694                               .map(|a| a.to_string())
2695                               .collect::<Vec<_>>()
2696                               .join(", ")
2697                       },
2698                       if curves_got.is_empty() {
2699                           "(none)".to_string()
2700                       } else {
2701                           curves_got
2702                               .iter()
2703                               .map(|a| a.to_string())
2704                               .collect::<Vec<_>>()
2705                               .join(", ")
2706                       });
2707        }
2708    }
2709
2710    #[test]
2711    fn for_encryption_for_signing() {
2712        // Override the algorithm using `PublicKeyAlgorithmSpecification`s..
2713        let p = &P::new();
2714
2715        // Try a few combinations.
2716        let rsa = PublicKeyAlgorithmSpecification::rsa(4096);
2717        let nist_signing = PublicKeyAlgorithmSpecification::nistp256_for_signing();
2718        let ed25519 = PublicKeyAlgorithmSpecification::ed25519();
2719
2720        let cv25519 = PublicKeyAlgorithmSpecification::legacy_cv25519();
2721        let bp_encryption = PublicKeyAlgorithmSpecification::brainpoolp256_for_encryption();
2722
2723        for signing in [ rsa.clone(), nist_signing.clone(), ed25519.clone() ] {
2724            for encryption in [ rsa.clone(), cv25519.clone(), bp_encryption.clone() ] {
2725                eprintln!("Testing {:?} and {:?}", signing, encryption);
2726                if ! signing.is_supported() {
2727                    eprintln!("Skipping, {:?} is not supported", signing);
2728                    continue;
2729                }
2730                if ! encryption.is_supported() {
2731                    eprintln!("Skipping, {:?} is not supported", signing);
2732                    continue;
2733                }
2734
2735                let (cert, _) = CertBuilder::general_purpose(Some("alice@example.org"))
2736                    .set_encryption_algorithm(encryption.clone())
2737                    .set_signing_algorithm(signing.clone())
2738                    // Add some extra subkeys.
2739                    .add_signing_subkey()
2740                    .add_transport_encryption_subkey()
2741                    .generate()
2742                    .expect("can create key");
2743
2744                cert
2745                    .with_policy(p, None).expect("valid cert")
2746                    .keys()
2747                    .for_each(|k| {
2748                        let flags = k.key_flags().expect("non-empty key flags");
2749
2750                        let for_signing = flags.for_signing()
2751                            || flags.for_certification()
2752                            || flags.for_authentication();
2753                        let for_encryption = flags.for_transport_encryption()
2754                            || flags.for_storage_encryption();
2755
2756                        // One or the other, but not both.
2757                        assert_eq!(for_signing, ! for_encryption);
2758
2759                        if for_signing {
2760                            assert_eq!(k.key().pk_algo(),
2761                                       signing.pk_algo());
2762                        } else {
2763                            assert_eq!(k.key().pk_algo(),
2764                                       encryption.pk_algo());
2765                        }
2766                    })
2767            }
2768        }
2769
2770        CertBuilder::general_purpose(Some("alice@example.org"))
2771            .set_encryption_algorithm(cv25519.clone())
2772            .set_signing_algorithm(cv25519.clone())
2773            .generate()
2774            .expect_err("can't use encryption algorithm for signing keys");
2775
2776        CertBuilder::general_purpose(Some("alice@example.org"))
2777            .set_encryption_algorithm(ed25519.clone())
2778            .set_signing_algorithm(ed25519.clone())
2779            .generate()
2780            .expect_err("can't use signing algorithm for encryption keys");
2781    }
2782}