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