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