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