sequoia_openpgp/packet/key.rs
1//! Key-related functionality.
2//!
3//! # Data Types
4//!
5//! The main data type is the [`Key`] enum. This enum abstracts away
6//! the differences between the key formats (the current [version 6],
7//! the deprecated [version 4], and the legacy [version 3]).
8//! Nevertheless, some functionality remains format specific. For
9//! instance, the `Key` enum doesn't provide a mechanism to generate
10//! keys. This functionality depends on the format.
11//!
12//! This version of Sequoia only supports version 6 and version 4 keys
13//! ([`Key6`], and [`Key4`]). However, future versions may include
14//! limited support for version 3 keys to allow working with archived
15//! messages.
16//!
17//! OpenPGP specifies four different types of keys: [public keys],
18//! [secret keys], [public subkeys], and [secret subkeys]. These are
19//! all represented by the `Key` enum and the `Key4` struct using
20//! marker types. We use marker types rather than an enum, to better
21//! exploit the type checking. For instance, type-specific methods
22//! like [`Key4::secret`] are only exposed for those types that
23//! actually support them. See the documentation for [`Key`] for an
24//! explanation of how the markers work.
25//!
26//! The [`SecretKeyMaterial`] data type allows working with secret key
27//! material directly. This enum has two variants: [`Unencrypted`],
28//! and [`Encrypted`]. It is not normally necessary to use this data
29//! structure directly. The primary functionality that is of interest
30//! to most users is decrypting secret key material. This is usually
31//! more conveniently done using [`Key::decrypt_secret`].
32//!
33//! [`Key`]: super::Key
34//! [version 3]: https://tools.ietf.org/html/rfc1991#section-6.6
35//! [version 4]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.2
36//! [version 6]: https://www.rfc-editor.org/rfc/rfc9580.html#name-version-6-public-keys
37//! [public keys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.1
38//! [secret keys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.3
39//! [public subkeys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.2
40//! [secret subkeys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.5
41//! [`Key::decrypt_secret`]: super::Key::decrypt_secret()
42//!
43//! # Key Creation
44//!
45//! Use [`Key6::generate_x25519`], [`Key6::generate_ed25519`],
46//! [`Key6::generate_x448`], [`Key6::generate_ed448`],
47//! [`Key6::generate_ecc`], or [`Key6::generate_rsa`] to create a new
48//! key.
49//!
50//! Existing key material can be turned into an OpenPGP key using
51//! [`Key6::import_public_x25519`], [`Key6::import_public_ed25519`],
52//! [`Key6::import_public_x448`], [`Key6::import_public_ed448`],
53//! [`Key6::import_public_rsa`], [`Key6::import_secret_x25519`],
54//! [`Key6::import_secret_ed25519`], [`Key6::import_secret_x448`],
55//! [`Key6::import_secret_ed448`], and [`Key6::import_secret_rsa`].
56//!
57//! Whether you create a new key or import existing key material, you
58//! still need to create a binding signature, and, for signing keys, a
59//! back signature for the key to be usable.
60//!
61//! # In-Memory Protection of Secret Key Material
62//!
63//! Whether the secret key material is protected on disk or not,
64//! Sequoia encrypts unencrypted secret key material ([`Unencrypted`])
65//! while it is memory. This helps protect against [heartbleed]-style
66//! attacks where a buffer over-read allows an attacker to read from
67//! the process's address space. This protection is less important
68//! for Rust programs, which are memory safe. However, it is
69//! essential when Sequoia is used via its FFI.
70//!
71//! See [`crypto::mem::Encrypted`] for details.
72//!
73//! [heartbleed]: https://en.wikipedia.org/wiki/Heartbleed
74//! [`crypto::mem::Encrypted`]: super::super::crypto::mem::Encrypted
75
76use std::fmt;
77use std::convert::TryInto;
78use std::hash::Hasher;
79
80#[cfg(test)]
81use quickcheck::{Arbitrary, Gen};
82
83use crate::Error;
84use crate::cert::prelude::*;
85use crate::crypto::{self, mem, mpi, KeyPair};
86use crate::packet::prelude::*;
87use crate::policy::HashAlgoSecurity;
88use crate::PublicKeyAlgorithm;
89use crate::seal;
90use crate::SymmetricAlgorithm;
91use crate::HashAlgorithm;
92use crate::types::{
93 AEADAlgorithm,
94 Curve,
95};
96use crate::crypto::S2K;
97use crate::Result;
98use crate::crypto::Password;
99use crate::crypto::SessionKey;
100
101mod conversions;
102mod v6;
103pub use v6::Key6;
104mod v4;
105pub use v4::Key4;
106
107/// Holds a public key, public subkey, private key or private subkey packet.
108///
109/// The different `Key` packets are described in [Section 5.5 of RFC 9580].
110///
111/// [Section 5.5 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5
112///
113/// # Key Variants
114///
115/// There are four different types of keys in OpenPGP: [public keys],
116/// [secret keys], [public subkeys], and [secret subkeys]. Although
117/// the semantics of each type of key are slightly different, the
118/// underlying representation is identical (even a public key and a
119/// secret key are the same: the public key variant just contains 0
120/// bits of secret key material).
121///
122/// In Sequoia, we use a single type, `Key`, for all four variants.
123/// To improve type safety, we use marker traits rather than an `enum`
124/// to distinguish them. Specifically, we `Key` is generic over two
125/// type variables, `P` and `R`.
126///
127/// `P` and `R` take marker traits, which describe how any secret key
128/// material should be treated, and the key's role (primary or
129/// subordinate). The markers also determine the `Key`'s behavior and
130/// the exposed functionality. `P` can be [`key::PublicParts`],
131/// [`key::SecretParts`], or [`key::UnspecifiedParts`]. And, `R` can
132/// be [`key::PrimaryRole`], [`key::SubordinateRole`], or
133/// [`key::UnspecifiedRole`].
134///
135/// If `P` is `key::PublicParts`, any secret key material that is
136/// present is ignored. For instance, when serializing a key with
137/// this marker, any secret key material will be skipped. This is
138/// illutrated in the following example. If `P` is
139/// `key::SecretParts`, then the key definitely contains secret key
140/// material (although it is not guaranteed that the secret key
141/// material is valid), and methods that require secret key material
142/// are available.
143///
144/// Unlike `P`, `R` does not say anything about the `Key`'s content.
145/// But, a key's role does influence's the key's semantics. For
146/// instance, some of a primary key's meta-data is located on the
147/// primary User ID whereas a subordinate key's meta-data is located
148/// on its binding signature.
149///
150/// The unspecified variants [`key::UnspecifiedParts`] and
151/// [`key::UnspecifiedRole`] exist to simplify type erasure, which is
152/// needed to mix different types of keys in a single collection. For
153/// instance, [`Cert::keys`] returns an iterator over the keys in a
154/// certificate. Since the keys have different roles (a primary key
155/// and zero or more subkeys), but the `Iterator` has to be over a
156/// single, fixed type, the returned keys use the
157/// `key::UnspecifiedRole` marker.
158///
159/// [public keys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.1
160/// [secret keys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.3
161/// [public subkeys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.2
162/// [secret subkeys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.5
163/// [`Cert::keys`]: crate::Cert::keys
164///
165/// ## Examples
166///
167/// Serializing a public key with secret key material drops the secret
168/// key material:
169///
170/// ```
171/// use sequoia_openpgp as openpgp;
172/// use openpgp::cert::prelude::*;
173/// use openpgp::packet::prelude::*;
174/// use sequoia_openpgp::parse::Parse;
175/// use openpgp::serialize::Serialize;
176///
177/// # fn main() -> openpgp::Result<()> {
178/// // Generate a new certificate. It has secret key material.
179/// let (cert, _) = CertBuilder::new()
180/// .generate()?;
181///
182/// let pk = cert.primary_key().key();
183/// assert!(pk.has_secret());
184///
185/// // Serializing a `Key<key::PublicParts, _>` drops the secret key
186/// // material.
187/// let mut bytes = Vec::new();
188/// Packet::from(pk.clone()).serialize(&mut bytes);
189/// let p : Packet = Packet::from_bytes(&bytes)?;
190///
191/// if let Packet::PublicKey(key) = p {
192/// assert!(! key.has_secret());
193/// } else {
194/// unreachable!();
195/// }
196/// # Ok(())
197/// # }
198/// ```
199///
200/// # Conversions
201///
202/// Sometimes it is necessary to change a marker. For instance, to
203/// help prevent a user from inadvertently leaking secret key
204/// material, the [`Cert`] data structure never returns keys with the
205/// [`key::SecretParts`] marker. This means, to use any secret key
206/// material, e.g., when creating a [`Signer`], the user needs to
207/// explicitly opt-in by changing the marker using
208/// [`Key::parts_into_secret`] or [`Key::parts_as_secret`].
209///
210/// For `P`, the conversion functions are: [`Key::parts_into_public`],
211/// [`Key::parts_as_public`], [`Key::parts_into_secret`],
212/// [`Key::parts_as_secret`], [`Key::parts_into_unspecified`], and
213/// [`Key::parts_as_unspecified`]. With the exception of converting
214/// `P` to `key::SecretParts`, these functions are infallible.
215/// Converting `P` to `key::SecretParts` may fail if the key doesn't
216/// have any secret key material. (Note: although the secret key
217/// material is required, it is not checked for validity.)
218///
219/// For `R`, the conversion functions are [`Key::role_into_primary`],
220/// [`Key::role_as_primary`], [`Key::role_into_subordinate`],
221/// [`Key::role_as_subordinate`], [`Key::role_into_unspecified`], and
222/// [`Key::role_as_unspecified`].
223///
224/// It is also possible to use `From`.
225///
226/// [`Signer`]: crate::crypto::Signer
227/// [`Key::parts_as_secret`]: Key::parts_as_secret()
228/// [`Key::parts_into_public`]: Key::parts_into_public()
229/// [`Key::parts_as_public`]: Key::parts_as_public()
230/// [`Key::parts_into_secret`]: Key::parts_into_secret()
231/// [`Key::parts_as_secret`]: Key::parts_as_secret()
232/// [`Key::parts_into_unspecified`]: Key::parts_into_unspecified()
233/// [`Key::parts_as_unspecified`]: Key::parts_as_unspecified()
234/// [`Key::role_into_primary`]: Key::role_into_primary()
235/// [`Key::role_as_primary`]: Key::role_as_primary()
236/// [`Key::role_into_subordinate`]: Key::role_into_subordinate()
237/// [`Key::role_as_subordinate`]: Key::role_as_subordinate()
238/// [`Key::role_into_unspecified`]: Key::role_into_unspecified()
239/// [`Key::role_as_unspecified`]: Key::role_as_unspecified()
240///
241/// ## Examples
242///
243/// Changing a marker:
244///
245/// ```
246/// use sequoia_openpgp as openpgp;
247/// use openpgp::cert::prelude::*;
248/// use openpgp::packet::prelude::*;
249///
250/// # fn main() -> openpgp::Result<()> {
251/// // Generate a new certificate. It has secret key material.
252/// let (cert, _) = CertBuilder::new()
253/// .generate()?;
254///
255/// let pk: &Key<key::PublicParts, key::PrimaryRole>
256/// = cert.primary_key().key();
257/// // `has_secret`s is one of the few methods that ignores the
258/// // parts type.
259/// assert!(pk.has_secret());
260///
261/// // Treat it like a secret key. This only works if `pk` really
262/// // has secret key material (which it does in this case, see above).
263/// let sk = pk.parts_as_secret()?;
264/// assert!(sk.has_secret());
265///
266/// // And back.
267/// let pk = sk.parts_as_public();
268/// // Yes, the secret key material is still there.
269/// assert!(pk.has_secret());
270/// # Ok(())
271/// # }
272/// ```
273///
274/// The [`Cert`] data structure only returns public keys. To work
275/// with any secret key material, the `Key` first needs to be
276/// converted to a secret key. This is necessary, for instance, when
277/// creating a [`Signer`]:
278///
279/// [`Cert`]: crate::Cert
280///
281/// ```rust
282/// use std::time;
283/// use sequoia_openpgp as openpgp;
284/// # use openpgp::Result;
285/// use openpgp::cert::prelude::*;
286/// use openpgp::crypto::KeyPair;
287/// use openpgp::policy::StandardPolicy;
288///
289/// # fn main() -> Result<()> {
290/// let p = &StandardPolicy::new();
291///
292/// let the_past = time::SystemTime::now() - time::Duration::from_secs(1);
293/// let (cert, _) = CertBuilder::new()
294/// .set_creation_time(the_past)
295/// .generate()?;
296///
297/// // Set the certificate to expire now. To do this, we need
298/// // to create a new self-signature, and sign it using a
299/// // certification-capable key. The primary key is always
300/// // certification capable.
301/// let mut keypair = cert.primary_key()
302/// .key().clone().parts_into_secret()?.into_keypair()?;
303/// let sigs = cert.set_expiration_time(p, None, &mut keypair,
304/// Some(time::SystemTime::now()))?;
305///
306/// let cert = cert.insert_packets(sigs)?.0;
307/// // It's expired now.
308/// assert!(cert.with_policy(p, None)?.alive().is_err());
309/// # Ok(())
310/// # }
311/// ```
312///
313/// # Key Generation
314///
315/// `Key` is a wrapper around [the different key formats].
316/// (Currently, Sequoia only supports version 6 and version 4 keys,
317/// however, future versions may add limited support for version 3
318/// keys to facilitate working with achieved messages.) As such, it
319/// doesn't provide a mechanism to generate keys or import existing
320/// key material. Instead, use the format-specific functions (e.g.,
321/// [`Key6::generate_ecc`]) and then convert the result into a `Key`
322/// packet, as the following example demonstrates.
323///
324/// [the different key formats]: https://www.rfc-editor.org/rfc/rfc9580.html#name-public-key-packet-formats
325///
326/// ## Examples
327///
328/// ```
329/// use sequoia_openpgp as openpgp;
330/// use openpgp::packet::prelude::*;
331/// use openpgp::types::Curve;
332///
333/// # fn main() -> openpgp::Result<()> {
334/// let key: Key<key::SecretParts, key::PrimaryRole>
335/// = Key::from(Key6::generate_ecc(true, Curve::Ed25519)?);
336/// # Ok(())
337/// # }
338/// ```
339///
340/// # Password Protection
341///
342/// OpenPGP provides a mechanism to [password protect keys]. If a key
343/// is password protected, you need to decrypt the password using
344/// [`Key::decrypt_secret`] before using its secret key material
345/// (e.g., to decrypt a message, or to generate a signature).
346///
347/// [password protect keys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-3.7
348/// [`Key::decrypt_secret`]: Key::decrypt_secret()
349///
350/// # A note on equality
351///
352/// The implementation of `Eq` for `Key` compares the serialized form
353/// of `Key`s. Comparing or serializing values of `Key<PublicParts,
354/// _>` ignore secret key material, whereas the secret key material is
355/// considered and serialized for `Key<SecretParts, _>`, and for
356/// `Key<UnspecifiedParts, _>` if present. To explicitly exclude the
357/// secret key material from the comparison, use [`Key::public_cmp`]
358/// or [`Key::public_eq`].
359///
360/// When merging in secret key material from untrusted sources, you
361/// need to be very careful: secret key material is not
362/// cryptographically protected by the key's self signature. Thus, an
363/// attacker can provide a valid key with a valid self signature, but
364/// invalid secret key material. If naively merged, this could
365/// overwrite valid secret key material, and thereby render the key
366/// useless. Unfortunately, the only way to find out that the secret
367/// key material is bad is to actually try using it. But, because the
368/// secret key material is usually encrypted, this can't always be
369/// done automatically.
370///
371/// [`Key::public_cmp`]: Key::public_cmp()
372/// [`Key::public_eq`]: Key::public_eq()
373///
374/// Compare:
375///
376/// ```
377/// use sequoia_openpgp as openpgp;
378/// use openpgp::cert::prelude::*;
379/// use openpgp::packet::prelude::*;
380/// use openpgp::packet::key::*;
381///
382/// # fn main() -> openpgp::Result<()> {
383/// // Generate a new certificate. It has secret key material.
384/// let (cert, _) = CertBuilder::new()
385/// .generate()?;
386///
387/// let sk: &Key<PublicParts, _> = cert.primary_key().key();
388/// assert!(sk.has_secret());
389///
390/// // Strip the secret key material.
391/// let cert = cert.clone().strip_secret_key_material();
392/// let pk: &Key<PublicParts, _> = cert.primary_key().key();
393/// assert!(! pk.has_secret());
394///
395/// // Eq on Key<PublicParts, _> compares only the public bits, so it
396/// // considers pk and sk to be equal.
397/// assert_eq!(pk, sk);
398///
399/// // Convert to Key<UnspecifiedParts, _>.
400/// let sk: &Key<UnspecifiedParts, _> = sk.parts_as_unspecified();
401/// let pk: &Key<UnspecifiedParts, _> = pk.parts_as_unspecified();
402///
403/// // Eq on Key<UnspecifiedParts, _> compares both the public and the
404/// // secret bits, so it considers pk and sk to be different.
405/// assert_ne!(pk, sk);
406///
407/// // In any case, Key::public_eq only compares the public bits,
408/// // so it considers them to be equal.
409/// assert!(Key::public_eq(pk, sk));
410/// # Ok(())
411/// # }
412/// ```
413#[non_exhaustive]
414#[derive(PartialEq, Eq, Hash, Debug)]
415pub enum Key<P: key::KeyParts, R: key::KeyRole> {
416 /// A version 4 `Key` packet.
417 V4(Key4<P, R>),
418
419 /// A version 6 `Key` packet.
420 V6(Key6<P, R>),
421}
422assert_send_and_sync!(Key<P, R> where P: key::KeyParts, R: key::KeyRole);
423
424// derive(Clone) doesn't work as expected with generic type parameters
425// that don't implement clone: it adds a trait bound on Clone to P and
426// R in the Clone implementation. Happily, we don't need P or R to
427// implement Clone: they are just marker traits, which we can clone
428// manually.
429//
430// See: https://github.com/rust-lang/rust/issues/26925
431impl<P, R> Clone for Key<P, R>
432 where P: key::KeyParts, R: key::KeyRole
433{
434 fn clone(&self) -> Self {
435 match self {
436 Key::V4(key) => Key::V4(key.clone()),
437 Key::V6(key) => Key::V6(key.clone()),
438 }
439 }
440}
441
442impl<P: key::KeyParts, R: key::KeyRole> fmt::Display for Key<P, R> {
443 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
444 match self {
445 Key::V4(k) => k.fmt(f),
446 Key::V6(k) => k.fmt(f),
447 }
448 }
449}
450
451impl From<Key<key::PublicParts, key::PrimaryRole>> for Packet {
452 /// Convert the `Key` struct to a `Packet`.
453 fn from(k: Key<key::PublicParts, key::PrimaryRole>) -> Self {
454 Packet::PublicKey(k)
455 }
456}
457
458impl From<Key<key::PublicParts, key::SubordinateRole>> for Packet {
459 /// Convert the `Key` struct to a `Packet`.
460 fn from(k: Key<key::PublicParts, key::SubordinateRole>) -> Self {
461 Packet::PublicSubkey(k)
462 }
463}
464
465impl From<Key<key::SecretParts, key::PrimaryRole>> for Packet {
466 /// Convert the `Key` struct to a `Packet`.
467 fn from(k: Key<key::SecretParts, key::PrimaryRole>) -> Self {
468 Packet::SecretKey(k)
469 }
470}
471
472impl From<Key<key::SecretParts, key::SubordinateRole>> for Packet {
473 /// Convert the `Key` struct to a `Packet`.
474 fn from(k: Key<key::SecretParts, key::SubordinateRole>) -> Self {
475 Packet::SecretSubkey(k)
476 }
477}
478
479impl<R: key::KeyRole> Key<key::SecretParts, R> {
480 /// Gets the `Key`'s `SecretKeyMaterial`.
481 pub fn secret(&self) -> &SecretKeyMaterial {
482 match self {
483 Key::V4(k) => k.secret(),
484 Key::V6(k) => k.secret(),
485 }
486 }
487
488 /// Gets a mutable reference to the `Key`'s `SecretKeyMaterial`.
489 pub fn secret_mut(&mut self) -> &mut SecretKeyMaterial {
490 match self {
491 Key::V4(k) => k.secret_mut(),
492 Key::V6(k) => k.secret_mut(),
493 }
494 }
495
496 /// Creates a new key pair from a `Key` with an unencrypted
497 /// secret key.
498 ///
499 /// If the `Key` is password protected, you first need to decrypt
500 /// it using [`Key::decrypt_secret`].
501 ///
502 /// [`Key::decrypt_secret`]: Key::decrypt_secret()
503 ///
504 /// # Errors
505 ///
506 /// Fails if the secret key is encrypted.
507 ///
508 /// # Examples
509 ///
510 /// Revoke a certificate by signing a new revocation certificate:
511 ///
512 /// ```rust
513 /// use std::time;
514 /// use sequoia_openpgp as openpgp;
515 /// # use openpgp::Result;
516 /// use openpgp::cert::prelude::*;
517 /// use openpgp::crypto::KeyPair;
518 /// use openpgp::types::ReasonForRevocation;
519 ///
520 /// # fn main() -> Result<()> {
521 /// // Generate a certificate.
522 /// let (cert, _) =
523 /// CertBuilder::general_purpose(Some("Alice Lovelace <alice@example.org>"))
524 /// .generate()?;
525 ///
526 /// // Use the secret key material to sign a revocation certificate.
527 /// let mut keypair = cert.primary_key()
528 /// .key().clone().parts_into_secret()?
529 /// .into_keypair()?;
530 /// let rev = cert.revoke(&mut keypair,
531 /// ReasonForRevocation::KeyCompromised,
532 /// b"It was the maid :/")?;
533 /// # Ok(())
534 /// # }
535 /// ```
536 pub fn into_keypair(self) -> Result<KeyPair> {
537 match self {
538 Key::V4(k) => k.into_keypair(),
539 Key::V6(k) => k.into_keypair(),
540 }
541 }
542
543 /// Decrypts the secret key material.
544 ///
545 /// In OpenPGP, secret key material can be [protected with a
546 /// password]. The password is usually hardened using a [KDF].
547 ///
548 /// [protected with a password]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.3
549 /// [KDF]: https://www.rfc-editor.org/rfc/rfc9580.html#section-3.7
550 ///
551 /// This function takes ownership of the `Key`, decrypts the
552 /// secret key material using the password, and returns a new key
553 /// whose secret key material is not password protected.
554 ///
555 /// If the secret key material is not password protected or if the
556 /// password is wrong, this function returns an error.
557 ///
558 /// # Examples
559 ///
560 /// Sign a new revocation certificate using a password-protected
561 /// key:
562 ///
563 /// ```rust
564 /// use sequoia_openpgp as openpgp;
565 /// # use openpgp::Result;
566 /// use openpgp::cert::prelude::*;
567 /// use openpgp::types::ReasonForRevocation;
568 ///
569 /// # fn main() -> Result<()> {
570 /// // Generate a certificate whose secret key material is
571 /// // password protected.
572 /// let (cert, _) =
573 /// CertBuilder::general_purpose(Some("Alice Lovelace <alice@example.org>"))
574 /// .set_password(Some("1234".into()))
575 /// .generate()?;
576 ///
577 /// // Use the secret key material to sign a revocation certificate.
578 /// let key = cert.primary_key().key().clone().parts_into_secret()?;
579 ///
580 /// // We can't turn it into a keypair without decrypting it.
581 /// assert!(key.clone().into_keypair().is_err());
582 ///
583 /// // And, we need to use the right password.
584 /// assert!(key.clone()
585 /// .decrypt_secret(&"correct horse battery staple".into())
586 /// .is_err());
587 ///
588 /// // Let's do it right:
589 /// let mut keypair = key.decrypt_secret(&"1234".into())?.into_keypair()?;
590 /// let rev = cert.revoke(&mut keypair,
591 /// ReasonForRevocation::KeyCompromised,
592 /// b"It was the maid :/")?;
593 /// # Ok(())
594 /// # }
595 /// ```
596 pub fn decrypt_secret(self, password: &Password) -> Result<Self>
597 {
598 match self {
599 Key::V4(k) => Ok(Key::V4(k.decrypt_secret(password)?)),
600 Key::V6(k) => Ok(Key::V6(k.decrypt_secret(password)?)),
601 }
602 }
603
604 /// Encrypts the secret key material.
605 ///
606 /// In OpenPGP, secret key material can be [protected with a
607 /// password]. The password is usually hardened using a [KDF].
608 ///
609 /// [protected with a password]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.3
610 /// [KDF]: https://www.rfc-editor.org/rfc/rfc9580.html#section-3.7
611 ///
612 /// This function takes ownership of the `Key`, encrypts the
613 /// secret key material using the password, and returns a new key
614 /// whose secret key material is protected with the password.
615 ///
616 /// If the secret key material is already password protected, this
617 /// function returns an error.
618 ///
619 /// # Examples
620 ///
621 /// This example demonstrates how to encrypt the secret key
622 /// material of every key in a certificate. Decryption can be
623 /// done the same way with [`Key::decrypt_secret`].
624 ///
625 /// ```rust
626 /// use sequoia_openpgp as openpgp;
627 /// # use openpgp::Result;
628 /// use openpgp::cert::prelude::*;
629 /// use openpgp::packet::Packet;
630 ///
631 /// # fn main() -> Result<()> {
632 /// // Generate a certificate whose secret key material is
633 /// // not password protected.
634 /// let (cert, _) =
635 /// CertBuilder::general_purpose(Some("Alice Lovelace <alice@example.org>"))
636 /// .generate()?;
637 ///
638 /// // Encrypt every key.
639 /// let mut encrypted_keys: Vec<Packet> = Vec::new();
640 /// for ka in cert.keys().secret() {
641 /// assert!(ka.key().has_unencrypted_secret());
642 ///
643 /// // Encrypt the key's secret key material.
644 /// let key = ka.key().clone().encrypt_secret(&"1234".into())?;
645 /// assert!(! key.has_unencrypted_secret());
646 ///
647 /// // We cannot merge it right now, because `cert` is borrowed.
648 /// encrypted_keys.push(if ka.primary() {
649 /// key.role_into_primary().into()
650 /// } else {
651 /// key.role_into_subordinate().into()
652 /// });
653 /// }
654 ///
655 /// // Merge the keys into the certificate. Note: `Cert::insert_packets`
656 /// // prefers added versions of keys. So, the encrypted version
657 /// // will override the decrypted version.
658 /// let cert = cert.insert_packets(encrypted_keys)?.0;
659 ///
660 /// // Now the every key's secret key material is encrypted. We'll
661 /// // demonstrate this using the primary key:
662 /// let key = cert.primary_key().key().parts_as_secret()?;
663 /// assert!(! key.has_unencrypted_secret());
664 ///
665 /// // We can't turn it into a keypair without decrypting it.
666 /// assert!(key.clone().into_keypair().is_err());
667 ///
668 /// // And, we need to use the right password.
669 /// assert!(key.clone()
670 /// .decrypt_secret(&"correct horse battery staple".into())
671 /// .is_err());
672 ///
673 /// // Let's do it right:
674 /// let mut keypair = key.clone()
675 /// .decrypt_secret(&"1234".into())?.into_keypair()?;
676 /// # Ok(())
677 /// # }
678 /// ```
679 pub fn encrypt_secret(self, password: &Password) -> Result<Self>
680 {
681 match self {
682 Key::V4(k) => Ok(Key::V4(k.encrypt_secret(password)?)),
683 Key::V6(k) => Ok(Key::V6(k.encrypt_secret(password)?)),
684 }
685 }
686}
687
688macro_rules! impl_common_secret_functions {
689 ($t: path) => {
690 /// Secret key handling.
691 impl<R: key::KeyRole> Key<$t, R> {
692 /// Takes the key packet's `SecretKeyMaterial`, if any.
693 pub fn take_secret(self)
694 -> (Key<key::PublicParts, R>,
695 Option<key::SecretKeyMaterial>)
696 {
697 match self {
698 Key::V4(k) => {
699 let (k, s) = k.take_secret();
700 (k.into(), s)
701 },
702 Key::V6(k) => {
703 let (k, s) = k.take_secret();
704 (k.into(), s)
705 },
706 }
707 }
708
709 /// Adds `SecretKeyMaterial` to the packet, returning the old if
710 /// any.
711 pub fn add_secret(self, secret: key::SecretKeyMaterial)
712 -> (Key<key::SecretParts, R>,
713 Option<key::SecretKeyMaterial>)
714 {
715 match self {
716 Key::V4(k) => {
717 let (k, s) = k.add_secret(secret);
718 (k.into(), s)
719 },
720 Key::V6(k) => {
721 let (k, s) = k.add_secret(secret);
722 (k.into(), s)
723 },
724 }
725 }
726
727 /// Takes the key packet's `SecretKeyMaterial`, if any.
728 pub fn steal_secret(&mut self) -> Option<key::SecretKeyMaterial>
729 {
730 match self {
731 Key::V4(k) => k.steal_secret(),
732 Key::V6(k) => k.steal_secret(),
733 }
734 }
735 }
736 }
737}
738impl_common_secret_functions!(key::PublicParts);
739impl_common_secret_functions!(key::UnspecifiedParts);
740
741/// Secret key handling.
742impl<R: key::KeyRole> Key<key::SecretParts, R> {
743 /// Takes the key packet's `SecretKeyMaterial`.
744 pub fn take_secret(self)
745 -> (Key<key::PublicParts, R>, key::SecretKeyMaterial)
746 {
747 match self {
748 Key::V4(k) => {
749 let (k, s) = k.take_secret();
750 (k.into(), s)
751 },
752 Key::V6(k) => {
753 let (k, s) = k.take_secret();
754 (k.into(), s)
755 },
756 }
757 }
758
759 /// Adds `SecretKeyMaterial` to the packet, returning the old.
760 pub fn add_secret(self, secret: key::SecretKeyMaterial)
761 -> (Key<key::SecretParts, R>, key::SecretKeyMaterial)
762 {
763 match self {
764 Key::V4(k) => {
765 let (k, s) = k.add_secret(secret);
766 (k.into(), s)
767 },
768 Key::V6(k) => {
769 let (k, s) = k.add_secret(secret);
770 (k.into(), s)
771 },
772 }
773 }
774}
775
776/// Ordering, equality, and hashing on the public parts only.
777impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
778 /// Compares the public bits of two keys.
779 ///
780 /// This returns `Ordering::Equal` if the public MPIs, creation
781 /// time, and algorithm of the two `Key4`s match. This does not
782 /// consider the packets' encodings, packets' tags or their secret
783 /// key material.
784 pub fn public_cmp<PB, RB>(&self, b: &Key<PB, RB>)
785 -> std::cmp::Ordering
786 where
787 PB: key::KeyParts,
788 RB: key::KeyRole,
789 {
790 match (self, b) {
791 (Key::V4(a), Key::V4(b)) => a.public_cmp(b),
792 (Key::V6(a), Key::V6(b)) => a.public_cmp(b),
793 // XXX: is that okay?
794 (Key::V4(_), Key::V6(_)) => std::cmp::Ordering::Less,
795 (Key::V6(_), Key::V4(_)) => std::cmp::Ordering::Greater,
796 }
797 }
798
799 /// Tests whether two keys are equal modulo their secret key
800 /// material.
801 ///
802 /// This returns true if the public MPIs, creation time and
803 /// algorithm of the two `Key4`s match. This does not consider
804 /// the packets' encodings, packets' tags or their secret key
805 /// material.
806 pub fn public_eq<PB, RB>(&self, b: &Key<PB, RB>)
807 -> bool
808 where
809 PB: key::KeyParts,
810 RB: key::KeyRole,
811 {
812 self.public_cmp(b) == std::cmp::Ordering::Equal
813 }
814
815 /// Hashes everything but any secret key material into state.
816 ///
817 /// This is an alternate implementation of [`Hash`], which never
818 /// hashes the secret key material.
819 ///
820 /// [`Hash`]: std::hash::Hash
821 pub fn public_hash<H>(&self, state: &mut H)
822 where
823 H: Hasher,
824 {
825 use std::hash::Hash;
826
827 match self {
828 Key::V4(k) => k.common.hash(state),
829 Key::V6(k) => k.common.common.hash(state),
830 }
831 self.creation_time().hash(state);
832 self.pk_algo().hash(state);
833 Hash::hash(&self.mpis(), state);
834 }
835}
836
837/// Immutable key interface.
838impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
839 /// Gets the version.
840 pub fn version(&self) -> u8 {
841 match self {
842 Key::V4(_) => 4,
843 Key::V6(_) => 6,
844 }
845 }
846
847 /// Gets the `Key`'s creation time.
848 pub fn creation_time(&self) -> std::time::SystemTime {
849 match self {
850 Key::V4(k) => k.creation_time(),
851 Key::V6(k) => k.creation_time(),
852 }
853 }
854
855 /// Sets the `Key`'s creation time.
856 ///
857 /// `timestamp` is converted to OpenPGP's internal format,
858 /// [`Timestamp`]: a 32-bit quantity containing the number of
859 /// seconds since the Unix epoch.
860 ///
861 /// `timestamp` is silently rounded to match the internal
862 /// resolution. An error is returned if `timestamp` is out of
863 /// range.
864 ///
865 /// [`Timestamp`]: crate::types::Timestamp
866 pub fn set_creation_time<T>(&mut self, timestamp: T)
867 -> Result<std::time::SystemTime>
868 where
869 T: Into<std::time::SystemTime>,
870 {
871 match self {
872 Key::V4(k) => k.set_creation_time(timestamp.into()),
873 Key::V6(k) => k.set_creation_time(timestamp.into()),
874 }
875 }
876
877 /// Gets the public key algorithm.
878 pub fn pk_algo(&self) -> PublicKeyAlgorithm {
879 match self {
880 Key::V4(k) => k.pk_algo(),
881 Key::V6(k) => k.pk_algo(),
882 }
883 }
884
885 /// Sets the public key algorithm.
886 ///
887 /// Returns the old public key algorithm.
888 pub fn set_pk_algo(&mut self, pk_algo: PublicKeyAlgorithm)
889 -> PublicKeyAlgorithm
890 {
891 match self {
892 Key::V4(k) => k.set_pk_algo(pk_algo),
893 Key::V6(k) => k.set_pk_algo(pk_algo),
894 }
895 }
896
897 /// Returns a reference to the `Key`'s MPIs.
898 pub fn mpis(&self) -> &mpi::PublicKey {
899 match self {
900 Key::V4(k) => k.mpis(),
901 Key::V6(k) => k.mpis(),
902 }
903 }
904
905 /// Returns a mutable reference to the `Key`'s MPIs.
906 pub fn mpis_mut(&mut self) -> &mut mpi::PublicKey {
907 match self {
908 Key::V4(k) => k.mpis_mut(),
909 Key::V6(k) => k.mpis_mut(),
910 }
911 }
912
913 /// Sets the `Key`'s MPIs.
914 ///
915 /// This function returns the old MPIs, if any.
916 pub fn set_mpis(&mut self, mpis: mpi::PublicKey) -> mpi::PublicKey {
917 match self {
918 Key::V4(k) => k.set_mpis(mpis),
919 Key::V6(k) => k.set_mpis(mpis),
920 }
921 }
922
923 /// Returns whether the `Key` contains secret key material.
924 pub fn has_secret(&self) -> bool {
925 match self {
926 Key::V4(k) => k.has_secret(),
927 Key::V6(k) => k.has_secret(),
928 }
929 }
930
931 /// Returns whether the `Key` contains unencrypted secret key
932 /// material.
933 ///
934 /// This returns false if the `Key` doesn't contain any secret key
935 /// material.
936 pub fn has_unencrypted_secret(&self) -> bool {
937 match self {
938 Key::V4(k) => k.has_unencrypted_secret(),
939 Key::V6(k) => k.has_unencrypted_secret(),
940 }
941 }
942
943 /// Returns `Key`'s secret key material, if any.
944 pub fn optional_secret(&self) -> Option<&SecretKeyMaterial> {
945 match self {
946 Key::V4(k) => k.optional_secret(),
947 Key::V6(k) => k.optional_secret(),
948 }
949 }
950
951 /// Computes and returns the `Key`'s `Fingerprint` and returns it as
952 /// a `KeyHandle`.
953 ///
954 /// See [Section 5.5.4 of RFC 9580].
955 ///
956 /// [Section 5.5.4 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.4
957 pub fn key_handle(&self) -> crate::KeyHandle {
958 match self {
959 Key::V4(k) => k.key_handle(),
960 Key::V6(k) => k.key_handle(),
961 }
962 }
963
964 /// Computes and returns the `Key`'s `Fingerprint`.
965 ///
966 /// See [Section 5.5.4 of RFC 9580].
967 ///
968 /// [Section 5.5.4 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.4
969 pub fn fingerprint(&self) -> crate::Fingerprint {
970 match self {
971 Key::V4(k) => k.fingerprint(),
972 Key::V6(k) => k.fingerprint(),
973 }
974 }
975
976 /// Computes and returns the `Key`'s `Key ID`.
977 ///
978 /// See [Section 5.5.4 of RFC 9580].
979 ///
980 /// [Section 5.5.4 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.4
981 pub fn keyid(&self) -> crate::KeyID {
982 match self {
983 Key::V4(k) => k.keyid(),
984 Key::V6(k) => k.keyid(),
985 }
986 }
987
988 /// The security requirements of the hash algorithm for
989 /// self-signatures.
990 ///
991 /// A cryptographic hash algorithm usually has [three security
992 /// properties]: pre-image resistance, second pre-image
993 /// resistance, and collision resistance. If an attacker can
994 /// influence the signed data, then the hash algorithm needs to
995 /// have both second pre-image resistance, and collision
996 /// resistance. If not, second pre-image resistance is
997 /// sufficient.
998 ///
999 /// [three security properties]: https://en.wikipedia.org/wiki/Cryptographic_hash_function#Properties
1000 ///
1001 /// In general, an attacker may be able to influence third-party
1002 /// signatures. But direct key signatures, and binding signatures
1003 /// are only over data fully determined by signer. And, an
1004 /// attacker's control over self signatures over User IDs is
1005 /// limited due to their structure.
1006 ///
1007 /// These observations can be used to extend the life of a hash
1008 /// algorithm after its collision resistance has been partially
1009 /// compromised, but not completely broken. For more details,
1010 /// please refer to the documentation for [HashAlgoSecurity].
1011 ///
1012 /// [HashAlgoSecurity]: crate::policy::HashAlgoSecurity
1013 pub fn hash_algo_security(&self) -> HashAlgoSecurity {
1014 HashAlgoSecurity::SecondPreImageResistance
1015 }
1016
1017 pub(crate) fn role(&self) -> key::KeyRoleRT {
1018 match self {
1019 Key::V4(k) => k.role(),
1020 Key::V6(k) => k.role(),
1021 }
1022 }
1023
1024 pub(crate) fn set_role(&mut self, role: key::KeyRoleRT) {
1025 match self {
1026 Key::V4(k) => k.set_role(role),
1027 Key::V6(k) => k.set_role(role),
1028 }
1029 }
1030}
1031
1032#[cfg(test)]
1033impl<P, R> Arbitrary for Key<P, R>
1034where
1035 P: KeyParts,
1036 R: KeyRole,
1037 Key4<P, R>: Arbitrary,
1038 Key6<P, R>: Arbitrary,
1039{
1040 fn arbitrary(g: &mut Gen) -> Self {
1041 if <bool>::arbitrary(g) {
1042 Key4::arbitrary(g).into()
1043 } else {
1044 Key6::arbitrary(g).into()
1045 }
1046 }
1047}
1048
1049/// A marker trait that captures whether a `Key` definitely contains
1050/// secret key material.
1051///
1052/// A [`Key`] can be treated as if it only has public key material
1053/// ([`key::PublicParts`]) or also has secret key material
1054/// ([`key::SecretParts`]). For those cases where the type
1055/// information needs to be erased (e.g., interfaces like
1056/// [`Cert::keys`]), we provide the [`key::UnspecifiedParts`] marker.
1057///
1058/// Even if a `Key` does not have the `SecretKey` marker, it may still
1059/// have secret key material. But, it will generally act as if it
1060/// didn't. In particular, when serializing a `Key` without the
1061/// `SecretKey` marker, secret key material will be ignored. See the
1062/// documentation for [`Key`] for a demonstration of this behavior.
1063///
1064/// [`Cert::keys`]: crate::cert::Cert::keys()
1065/// [`Key`]: super::Key
1066/// [`key::PublicParts`]: PublicParts
1067/// [`key::SecretParts`]: SecretParts
1068/// [`key::UnspecifiedParts`]: UnspecifiedParts
1069///
1070/// # Sealed trait
1071///
1072/// This trait is [sealed] and cannot be implemented for types outside this crate.
1073/// Therefore it can be extended in a non-breaking way.
1074/// If you want to implement the trait inside the crate
1075/// you also need to implement the `seal::Sealed` marker trait.
1076///
1077/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
1078pub trait KeyParts: fmt::Debug + seal::Sealed {
1079 /// Converts a key with unspecified parts into this kind of key.
1080 ///
1081 /// This function is helpful when you need to convert a concrete
1082 /// type into a generic type. Using `From` works, but requires
1083 /// adding a type bound to the generic type, which is ugly and
1084 /// invasive.
1085 ///
1086 /// Converting a key with [`key::PublicParts`] or
1087 /// [`key::UnspecifiedParts`] will always succeed. However,
1088 /// converting a key to one with [`key::SecretParts`] only
1089 /// succeeds if the key actually contains secret key material.
1090 ///
1091 /// [`key::PublicParts`]: PublicParts
1092 /// [`key::UnspecifiedParts`]: UnspecifiedParts
1093 /// [`key::SecretParts`]: SecretParts
1094 ///
1095 /// # Examples
1096 ///
1097 /// For a less construed example, refer to the [source code]:
1098 ///
1099 /// [source code]: https://gitlab.com/search?search=convert_key&project_id=4469613&search_code=true&repository_ref=master
1100 ///
1101 /// ```
1102 /// use sequoia_openpgp as openpgp;
1103 /// use openpgp::Result;
1104 /// # use openpgp::cert::prelude::*;
1105 /// use openpgp::packet::prelude::*;
1106 ///
1107 /// fn f<P>(cert: &Cert, mut key: Key<P, key::UnspecifiedRole>)
1108 /// -> Result<Key<P, key::UnspecifiedRole>>
1109 /// where P: key::KeyParts
1110 /// {
1111 /// // ...
1112 ///
1113 /// # let criterium = true;
1114 /// if criterium {
1115 /// // Cert::primary_key's return type is concrete
1116 /// // (Key<key::PublicParts, key::PrimaryRole>). We need to
1117 /// // convert it to the generic type Key<P, key::UnspecifiedRole>.
1118 /// // First, we "downcast" it to have unspecified parts and an
1119 /// // unspecified role, then we use a method defined by the
1120 /// // generic type to perform the conversion to the generic
1121 /// // type P.
1122 /// key = P::convert_key(
1123 /// cert.primary_key().key().clone()
1124 /// .parts_into_unspecified()
1125 /// .role_into_unspecified())?;
1126 /// }
1127 /// # else { unreachable!() }
1128 ///
1129 /// // ...
1130 ///
1131 /// Ok(key)
1132 /// }
1133 /// # fn main() -> openpgp::Result<()> {
1134 /// # let (cert, _) =
1135 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1136 /// # .generate()?;
1137 /// # f(&cert, cert.primary_key().key().clone().role_into_unspecified())?;
1138 /// # Ok(())
1139 /// # }
1140 /// ```
1141 fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>)
1142 -> Result<Key<Self, R>>
1143 where Self: Sized;
1144
1145 /// Converts a key reference with unspecified parts into this kind
1146 /// of key reference.
1147 ///
1148 /// This function is helpful when you need to convert a concrete
1149 /// type into a generic type. Using `From` works, but requires
1150 /// adding a type bound to the generic type, which is ugly and
1151 /// invasive.
1152 ///
1153 /// Converting a key with [`key::PublicParts`] or
1154 /// [`key::UnspecifiedParts`] will always succeed. However,
1155 /// converting a key to one with [`key::SecretParts`] only
1156 /// succeeds if the key actually contains secret key material.
1157 ///
1158 /// [`key::PublicParts`]: PublicParts
1159 /// [`key::UnspecifiedParts`]: UnspecifiedParts
1160 /// [`key::SecretParts`]: SecretParts
1161 fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>)
1162 -> Result<&Key<Self, R>>
1163 where Self: Sized;
1164
1165 /// Converts a key bundle with unspecified parts into this kind of
1166 /// key bundle.
1167 ///
1168 /// This function is helpful when you need to convert a concrete
1169 /// type into a generic type. Using `From` works, but requires
1170 /// adding a type bound to the generic type, which is ugly and
1171 /// invasive.
1172 ///
1173 /// Converting a key bundle with [`key::PublicParts`] or
1174 /// [`key::UnspecifiedParts`] will always succeed. However,
1175 /// converting a key bundle to one with [`key::SecretParts`] only
1176 /// succeeds if the key bundle actually contains secret key
1177 /// material.
1178 ///
1179 /// [`key::PublicParts`]: PublicParts
1180 /// [`key::UnspecifiedParts`]: UnspecifiedParts
1181 /// [`key::SecretParts`]: SecretParts
1182 fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>)
1183 -> Result<KeyBundle<Self, R>>
1184 where Self: Sized;
1185
1186 /// Converts a key bundle reference with unspecified parts into
1187 /// this kind of key bundle reference.
1188 ///
1189 /// This function is helpful when you need to convert a concrete
1190 /// type into a generic type. Using `From` works, but requires
1191 /// adding a type bound to the generic type, which is ugly and
1192 /// invasive.
1193 ///
1194 /// Converting a key bundle with [`key::PublicParts`] or
1195 /// [`key::UnspecifiedParts`] will always succeed. However,
1196 /// converting a key bundle to one with [`key::SecretParts`] only
1197 /// succeeds if the key bundle actually contains secret key
1198 /// material.
1199 ///
1200 /// [`key::PublicParts`]: PublicParts
1201 /// [`key::UnspecifiedParts`]: UnspecifiedParts
1202 /// [`key::SecretParts`]: SecretParts
1203 fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>)
1204 -> Result<&KeyBundle<Self, R>>
1205 where Self: Sized;
1206
1207 /// Converts a key amalgamation with unspecified parts into this
1208 /// kind of key amalgamation.
1209 ///
1210 /// This function is helpful when you need to convert a concrete
1211 /// type into a generic type. Using `From` works, but requires
1212 /// adding a type bound to the generic type, which is ugly and
1213 /// invasive.
1214 ///
1215 /// Converting a key amalgamation with [`key::PublicParts`] or
1216 /// [`key::UnspecifiedParts`] will always succeed. However,
1217 /// converting a key amalgamation to one with [`key::SecretParts`]
1218 /// only succeeds if the key amalgamation actually contains secret
1219 /// key material.
1220 ///
1221 /// [`key::PublicParts`]: PublicParts
1222 /// [`key::UnspecifiedParts`]: UnspecifiedParts
1223 /// [`key::SecretParts`]: SecretParts
1224 fn convert_key_amalgamation<R: KeyRole>(
1225 ka: ComponentAmalgamation<Key<UnspecifiedParts, R>>)
1226 -> Result<ComponentAmalgamation<Key<Self, R>>>
1227 where Self: Sized;
1228
1229 /// Converts a key amalgamation reference with unspecified parts
1230 /// into this kind of key amalgamation reference.
1231 ///
1232 /// This function is helpful when you need to convert a concrete
1233 /// type into a generic type. Using `From` works, but requires
1234 /// adding a type bound to the generic type, which is ugly and
1235 /// invasive.
1236 ///
1237 /// Converting a key amalgamation with [`key::PublicParts`] or
1238 /// [`key::UnspecifiedParts`] will always succeed. However,
1239 /// converting a key amalgamation to one with [`key::SecretParts`]
1240 /// only succeeds if the key amalgamation actually contains secret
1241 /// key material.
1242 ///
1243 /// [`key::PublicParts`]: PublicParts
1244 /// [`key::UnspecifiedParts`]: UnspecifiedParts
1245 /// [`key::SecretParts`]: SecretParts
1246 fn convert_key_amalgamation_ref<'a, R: KeyRole>(
1247 ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
1248 -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>>
1249 where Self: Sized;
1250
1251 /// Indicates that secret key material should be considered when
1252 /// comparing or hashing this key.
1253 fn significant_secrets() -> bool;
1254}
1255
1256/// A marker trait that captures a `Key`'s role.
1257///
1258/// A [`Key`] can either be a primary key ([`key::PrimaryRole`]) or a
1259/// subordinate key ([`key::SubordinateRole`]). For those cases where
1260/// the type information needs to be erased (e.g., interfaces like
1261/// [`Cert::keys`]), we provide the [`key::UnspecifiedRole`] marker.
1262///
1263/// [`Key`]: super::Key
1264/// [`key::PrimaryRole`]: PrimaryRole
1265/// [`key::SubordinateRole`]: SubordinateRole
1266/// [`Cert::keys`]: crate::cert::Cert::keys()
1267/// [`key::UnspecifiedRole`]: UnspecifiedRole
1268///
1269/// # Sealed trait
1270///
1271/// This trait is [sealed] and cannot be implemented for types outside this crate.
1272/// Therefore it can be extended in a non-breaking way.
1273/// If you want to implement the trait inside the crate
1274/// you also need to implement the `seal::Sealed` marker trait.
1275///
1276/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
1277pub trait KeyRole: fmt::Debug + seal::Sealed {
1278 /// Converts a key with an unspecified role into this kind of key.
1279 ///
1280 /// This function is helpful when you need to convert a concrete
1281 /// type into a generic type. Using `From` works, but requires
1282 /// adding a type bound to the generic type, which is ugly and
1283 /// invasive.
1284 ///
1285 /// # Examples
1286 ///
1287 /// ```
1288 /// use sequoia_openpgp as openpgp;
1289 /// use openpgp::Result;
1290 /// # use openpgp::cert::prelude::*;
1291 /// use openpgp::packet::prelude::*;
1292 ///
1293 /// fn f<R>(cert: &Cert, mut key: Key<key::UnspecifiedParts, R>)
1294 /// -> Result<Key<key::UnspecifiedParts, R>>
1295 /// where R: key::KeyRole
1296 /// {
1297 /// // ...
1298 ///
1299 /// # let criterium = true;
1300 /// if criterium {
1301 /// // Cert::primary_key's return type is concrete
1302 /// // (Key<key::PublicParts, key::PrimaryRole>). We need to
1303 /// // convert it to the generic type Key<key::UnspecifiedParts, R>.
1304 /// // First, we "downcast" it to have unspecified parts and an
1305 /// // unspecified role, then we use a method defined by the
1306 /// // generic type to perform the conversion to the generic
1307 /// // type R.
1308 /// key = R::convert_key(
1309 /// cert.primary_key().key().clone()
1310 /// .parts_into_unspecified()
1311 /// .role_into_unspecified());
1312 /// }
1313 /// # else { unreachable!() }
1314 ///
1315 /// // ...
1316 ///
1317 /// Ok(key)
1318 /// }
1319 /// # fn main() -> openpgp::Result<()> {
1320 /// # let (cert, _) =
1321 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1322 /// # .generate()?;
1323 /// # f(&cert, cert.primary_key().key().clone().parts_into_unspecified())?;
1324 /// # Ok(())
1325 /// # }
1326 /// ```
1327 fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>)
1328 -> Key<P, Self>
1329 where Self: Sized;
1330
1331 /// Converts a key reference with an unspecified role into this
1332 /// kind of key reference.
1333 ///
1334 /// This function is helpful when you need to convert a concrete
1335 /// type into a generic type. Using `From` works, but requires
1336 /// adding a type bound to the generic type, which is ugly and
1337 /// invasive.
1338 fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>)
1339 -> &Key<P, Self>
1340 where Self: Sized;
1341
1342 /// Converts a key bundle with an unspecified role into this kind
1343 /// of key bundle.
1344 ///
1345 /// This function is helpful when you need to convert a concrete
1346 /// type into a generic type. Using `From` works, but requires
1347 /// adding a type bound to the generic type, which is ugly and
1348 /// invasive.
1349 fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>)
1350 -> KeyBundle<P, Self>
1351 where Self: Sized;
1352
1353 /// Converts a key bundle reference with an unspecified role into
1354 /// this kind of key bundle reference.
1355 ///
1356 /// This function is helpful when you need to convert a concrete
1357 /// type into a generic type. Using `From` works, but requires
1358 /// adding a type bound to the generic type, which is ugly and
1359 /// invasive.
1360 fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>)
1361 -> &KeyBundle<P, Self>
1362 where Self: Sized;
1363
1364 /// Returns the role as a runtime value.
1365 fn role() -> KeyRoleRT;
1366}
1367
1368/// A marker that indicates that a `Key` should be treated like a
1369/// public key.
1370///
1371/// Note: this doesn't indicate whether the data structure contains
1372/// secret key material; it indicates whether any secret key material
1373/// should be ignored. For instance, when exporting a key with the
1374/// `PublicParts` marker, secret key material will *not* be exported.
1375/// See the documentation for [`Key`] for a demonstration.
1376///
1377/// Refer to [`KeyParts`] for details.
1378///
1379/// [`Key`]: super::Key
1380#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1381pub struct PublicParts;
1382
1383assert_send_and_sync!(PublicParts);
1384
1385impl seal::Sealed for PublicParts {}
1386impl KeyParts for PublicParts {
1387 fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>)
1388 -> Result<Key<Self, R>> {
1389 Ok(key.into())
1390 }
1391
1392 fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>)
1393 -> Result<&Key<Self, R>> {
1394 Ok(key.into())
1395 }
1396
1397 fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>)
1398 -> Result<KeyBundle<Self, R>> {
1399 Ok(bundle.into())
1400 }
1401
1402 fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>)
1403 -> Result<&KeyBundle<Self, R>> {
1404 Ok(bundle.into())
1405 }
1406
1407 fn convert_key_amalgamation<R: KeyRole>(
1408 ka: ComponentAmalgamation<Key<UnspecifiedParts, R>>)
1409 -> Result<ComponentAmalgamation<Key<Self, R>>> {
1410 Ok(ka.into())
1411 }
1412
1413 fn convert_key_amalgamation_ref<'a, R: KeyRole>(
1414 ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
1415 -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>> {
1416 Ok(ka.into())
1417 }
1418
1419 fn significant_secrets() -> bool {
1420 false
1421 }
1422}
1423
1424/// A marker that indicates that a `Key` should be treated like a
1425/// secret key.
1426///
1427/// Unlike the [`key::PublicParts`] marker, this marker asserts that
1428/// the [`Key`] contains secret key material. Because secret key
1429/// material is not protected by the self-signature, there is no
1430/// indication that the secret key material is actually valid.
1431///
1432/// Refer to [`KeyParts`] for details.
1433///
1434/// [`key::PublicParts`]: PublicParts
1435/// [`Key`]: super::Key
1436#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1437pub struct SecretParts;
1438
1439assert_send_and_sync!(SecretParts);
1440
1441impl seal::Sealed for SecretParts {}
1442impl KeyParts for SecretParts {
1443 fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>)
1444 -> Result<Key<Self, R>>{
1445 key.try_into()
1446 }
1447
1448 fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>)
1449 -> Result<&Key<Self, R>> {
1450 key.try_into()
1451 }
1452
1453 fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>)
1454 -> Result<KeyBundle<Self, R>> {
1455 bundle.try_into()
1456 }
1457
1458 fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>)
1459 -> Result<&KeyBundle<Self, R>> {
1460 bundle.try_into()
1461 }
1462
1463 fn convert_key_amalgamation<R: KeyRole>(
1464 ka: ComponentAmalgamation<Key<UnspecifiedParts, R>>)
1465 -> Result<ComponentAmalgamation<Key<Self, R>>> {
1466 ka.try_into()
1467 }
1468
1469 fn convert_key_amalgamation_ref<'a, R: KeyRole>(
1470 ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
1471 -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>> {
1472 ka.try_into()
1473 }
1474
1475 fn significant_secrets() -> bool {
1476 true
1477 }
1478}
1479
1480/// A marker that indicates that a `Key`'s parts are unspecified.
1481///
1482/// Neither public key-specific nor secret key-specific operations are
1483/// allowed on these types of keys. For instance, it is not possible
1484/// to export a key with the `UnspecifiedParts` marker, because it is
1485/// unclear how to treat any secret key material. To export such a
1486/// key, you need to first change the marker to [`key::PublicParts`]
1487/// or [`key::SecretParts`].
1488///
1489/// This marker is used when it is necessary to erase the type. For
1490/// instance, we need to do this when mixing [`Key`]s with different
1491/// markers in the same collection. See [`Cert::keys`] for an
1492/// example.
1493///
1494/// Refer to [`KeyParts`] for details.
1495///
1496/// [`key::PublicParts`]: PublicParts
1497/// [`key::SecretParts`]: SecretParts
1498/// [`Key`]: super::Key
1499/// [`Cert::keys`]: super::super::Cert::keys()
1500#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1501pub struct UnspecifiedParts;
1502
1503assert_send_and_sync!(UnspecifiedParts);
1504
1505impl seal::Sealed for UnspecifiedParts {}
1506impl KeyParts for UnspecifiedParts {
1507 fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>)
1508 -> Result<Key<Self, R>> {
1509 Ok(key)
1510 }
1511
1512 fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>)
1513 -> Result<&Key<Self, R>> {
1514 Ok(key)
1515 }
1516
1517 fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>)
1518 -> Result<KeyBundle<Self, R>> {
1519 Ok(bundle)
1520 }
1521
1522 fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>)
1523 -> Result<&KeyBundle<Self, R>> {
1524 Ok(bundle)
1525 }
1526
1527 fn convert_key_amalgamation<R: KeyRole>(
1528 ka: ComponentAmalgamation<Key<UnspecifiedParts, R>>)
1529 -> Result<ComponentAmalgamation<Key<UnspecifiedParts, R>>> {
1530 Ok(ka)
1531 }
1532
1533 fn convert_key_amalgamation_ref<'a, R: KeyRole>(
1534 ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
1535 -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>> {
1536 Ok(ka)
1537 }
1538
1539 fn significant_secrets() -> bool {
1540 true
1541 }
1542}
1543
1544/// A marker that indicates the `Key` should be treated like a primary key.
1545///
1546/// Refer to [`KeyRole`] for details.
1547///
1548#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1549pub struct PrimaryRole;
1550
1551assert_send_and_sync!(PrimaryRole);
1552
1553impl seal::Sealed for PrimaryRole {}
1554impl KeyRole for PrimaryRole {
1555 fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>)
1556 -> Key<P, Self> {
1557 key.into()
1558 }
1559
1560 fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>)
1561 -> &Key<P, Self> {
1562 key.into()
1563 }
1564
1565 fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>)
1566 -> KeyBundle<P, Self> {
1567 bundle.into()
1568 }
1569
1570 fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>)
1571 -> &KeyBundle<P, Self> {
1572 bundle.into()
1573 }
1574
1575 fn role() -> KeyRoleRT {
1576 KeyRoleRT::Primary
1577 }
1578}
1579
1580/// A marker that indicates the `Key` should be treated like a subkey.
1581///
1582/// Refer to [`KeyRole`] for details.
1583///
1584#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1585pub struct SubordinateRole;
1586
1587assert_send_and_sync!(SubordinateRole);
1588
1589impl seal::Sealed for SubordinateRole {}
1590impl KeyRole for SubordinateRole {
1591 fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>)
1592 -> Key<P, Self> {
1593 key.into()
1594 }
1595
1596 fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>)
1597 -> &Key<P, Self> {
1598 key.into()
1599 }
1600
1601 fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>)
1602 -> KeyBundle<P, Self> {
1603 bundle.into()
1604 }
1605
1606 fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>)
1607 -> &KeyBundle<P, Self> {
1608 bundle.into()
1609 }
1610
1611 fn role() -> KeyRoleRT {
1612 KeyRoleRT::Subordinate
1613 }
1614}
1615
1616/// A marker that indicates the `Key`'s role is unspecified.
1617///
1618/// Neither primary key-specific nor subkey-specific operations are
1619/// allowed. To perform those operations, the marker first has to be
1620/// changed to either [`key::PrimaryRole`] or
1621/// [`key::SubordinateRole`], as appropriate.
1622///
1623/// Refer to [`KeyRole`] for details.
1624///
1625/// [`key::PrimaryRole`]: PrimaryRole
1626/// [`key::SubordinateRole`]: SubordinateRole
1627#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1628pub struct UnspecifiedRole;
1629
1630assert_send_and_sync!(UnspecifiedRole);
1631
1632impl seal::Sealed for UnspecifiedRole {}
1633impl KeyRole for UnspecifiedRole {
1634 fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>)
1635 -> Key<P, Self> {
1636 key
1637 }
1638
1639 fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>)
1640 -> &Key<P, Self> {
1641 key
1642 }
1643
1644 fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>)
1645 -> KeyBundle<P, Self> {
1646 bundle
1647 }
1648
1649 fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>)
1650 -> &KeyBundle<P, Self> {
1651 bundle
1652 }
1653
1654 fn role() -> KeyRoleRT {
1655 KeyRoleRT::Unspecified
1656 }
1657}
1658
1659/// Encodes the key role at run time.
1660///
1661/// While `KeyRole` tracks the key's role in the type system,
1662/// `KeyRoleRT` tracks the key role at run time.
1663///
1664/// When we are doing a reference conversion (e.g. by using
1665/// [`Key::role_as_primary`]), we do not change the key's role. But,
1666/// when we are doing an owned conversion (e.g. by using
1667/// [`Key::role_into_primary`]), we do change the key's role. The
1668/// rationale here is that the former conversion is done to allow a
1669/// reference to be given to a function expecting a certain shape of
1670/// key (e.g. to prevent excessive monomorphization), while the latter
1671/// conversion signals intent (e.g. to put a key into a
1672/// `Packet::PublicKey`).
1673///
1674/// This is similar to how we have `KeyParts` that track the presence
1675/// or absence of secret key material in the type system, yet at run
1676/// time a key may or may not actually have secret key material (with
1677/// the constraint that a key with `SecretParts` MUST have secret key
1678/// material).
1679#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1680pub enum KeyRoleRT {
1681 /// The key is a primary key.
1682 Primary,
1683
1684 /// The key is a subkey.
1685 Subordinate,
1686
1687 /// The key's role is unspecified.
1688 Unspecified,
1689}
1690
1691/// A Public Key.
1692pub(crate) type PublicKey = Key<PublicParts, PrimaryRole>;
1693/// A Public Subkey.
1694pub(crate) type PublicSubkey = Key<PublicParts, SubordinateRole>;
1695/// A Secret Key.
1696pub(crate) type SecretKey = Key<SecretParts, PrimaryRole>;
1697/// A Secret Subkey.
1698pub(crate) type SecretSubkey = Key<SecretParts, SubordinateRole>;
1699
1700/// A key with public parts, and an unspecified role
1701/// (`UnspecifiedRole`).
1702#[allow(dead_code)]
1703pub(crate) type UnspecifiedPublic = Key<PublicParts, UnspecifiedRole>;
1704/// A key with secret parts, and an unspecified role
1705/// (`UnspecifiedRole`).
1706pub(crate) type UnspecifiedSecret = Key<SecretParts, UnspecifiedRole>;
1707
1708/// A primary key with unspecified parts (`UnspecifiedParts`).
1709#[allow(dead_code)]
1710pub(crate) type UnspecifiedPrimary = Key<UnspecifiedParts, PrimaryRole>;
1711/// A subkey key with unspecified parts (`UnspecifiedParts`).
1712#[allow(dead_code)]
1713pub(crate) type UnspecifiedSecondary = Key<UnspecifiedParts, SubordinateRole>;
1714
1715/// A key whose parts and role are unspecified
1716/// (`UnspecifiedParts`, `UnspecifiedRole`).
1717#[allow(dead_code)]
1718pub(crate) type UnspecifiedKey = Key<UnspecifiedParts, UnspecifiedRole>;
1719
1720/// Cryptographic operations using the key material.
1721impl<P, R> Key<P, R>
1722 where P: key::KeyParts,
1723 R: key::KeyRole,
1724{
1725 /// Encrypts the given data with this key.
1726 pub fn encrypt(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
1727 use crate::crypto::ecdh::aes_key_wrap;
1728 use crate::crypto::backend::{Backend, interface::{Asymmetric, Kdf}};
1729 use crate::crypto::mpi::PublicKey;
1730 use PublicKeyAlgorithm::*;
1731
1732 #[allow(deprecated, non_snake_case)]
1733 #[allow(clippy::erasing_op, clippy::identity_op)]
1734 match self.pk_algo() {
1735 X25519 =>
1736 if let mpi::PublicKey::X25519 { u: U } = self.mpis()
1737 {
1738 // Generate an ephemeral key pair {v, V=vG}
1739 let (v, V) = Backend::x25519_generate_key()?;
1740
1741 // Compute the shared point S = vU;
1742 let S = Backend::x25519_shared_point(&v, U)?;
1743
1744 // Compute the wrap key.
1745 let wrap_algo = SymmetricAlgorithm::AES128;
1746 let mut ikm: SessionKey = vec![0; 32 + 32 + 32].into();
1747 ikm[0 * 32..1 * 32].copy_from_slice(&V[..]);
1748 ikm[1 * 32..2 * 32].copy_from_slice(&U[..]);
1749 ikm[2 * 32..3 * 32].copy_from_slice(&S[..]);
1750 let mut kek = vec![0; wrap_algo.key_size()?].into();
1751 Backend::hkdf_sha256(&ikm, None, b"OpenPGP X25519", &mut kek)?;
1752
1753 let esk = aes_key_wrap(wrap_algo, kek.as_protected(),
1754 data.as_protected())?;
1755 Ok(mpi::Ciphertext::X25519 {
1756 e: Box::new(V),
1757 key: esk.into(),
1758 })
1759 } else {
1760 Err(Error::MalformedPacket(format!(
1761 "Key: Expected X25519 public key, got {:?}", self.mpis())).into())
1762 },
1763
1764 X448 =>
1765 if let mpi::PublicKey::X448 { u: U } = self.mpis()
1766 {
1767 let (v, V) = Backend::x448_generate_key()?;
1768
1769 // Compute the shared point S = vU;
1770 let S = Backend::x448_shared_point(&v, U)?;
1771
1772 // Compute the wrap key.
1773 let wrap_algo = SymmetricAlgorithm::AES256;
1774 let mut ikm: SessionKey = vec![0; 56 + 56 + 56].into();
1775 ikm[0 * 56..1 * 56].copy_from_slice(&V[..]);
1776 ikm[1 * 56..2 * 56].copy_from_slice(&U[..]);
1777 ikm[2 * 56..3 * 56].copy_from_slice(&S[..]);
1778 let mut kek = vec![0; wrap_algo.key_size()?].into();
1779 Backend::hkdf_sha512(&ikm, None, b"OpenPGP X448", &mut kek)?;
1780
1781 let esk = aes_key_wrap(wrap_algo, kek.as_protected(),
1782 data.as_protected())?;
1783 Ok(mpi::Ciphertext::X448 {
1784 e: Box::new(V),
1785 key: esk.into(),
1786 })
1787 } else {
1788 Err(Error::MalformedPacket(format!(
1789 "Key: Expected X448 public key, got {:?}", self.mpis())).into())
1790 },
1791
1792 MLKEM768_X25519 => if let mpi::PublicKey::MLKEM768_X25519 {
1793 ecdh: ecdh_public, mlkem: mlkem_public,
1794 } = self.mpis()
1795 {
1796 let (ecdh_secret, ecdh_ciphertext) =
1797 Backend::x25519_generate_key()?;
1798 let ecdh_keyshare = Backend::x25519_shared_point(
1799 &ecdh_secret, ecdh_public)?;
1800
1801 let (mlkem_ciphertext, mlkem_keyshare) =
1802 Backend::mlkem768_encapsulate(mlkem_public)?;
1803
1804 let kek = crate::crypto::asymmetric::multi_key_combine(
1805 &mlkem_keyshare,
1806 &ecdh_keyshare,
1807 ecdh_ciphertext.as_ref(),
1808 ecdh_public.as_ref(),
1809 PublicKeyAlgorithm::MLKEM768_X25519)?;
1810
1811 let esk = aes_key_wrap(SymmetricAlgorithm::AES256,
1812 kek.as_protected(),
1813 data.as_protected())?.into();
1814 Ok(mpi::Ciphertext::MLKEM768_X25519 {
1815 ecdh: Box::new(ecdh_ciphertext),
1816 mlkem: mlkem_ciphertext,
1817 esk,
1818 })
1819 } else {
1820 Err(Error::MalformedPacket(format!(
1821 "Key: Expected MLKEM768_X25519 public key, got {:?}",
1822 self.mpis())).into())
1823 },
1824
1825 MLKEM1024_X448 => if let mpi::PublicKey::MLKEM1024_X448 {
1826 ecdh: ecdh_public, mlkem: mlkem_public,
1827 } = self.mpis()
1828 {
1829 let (ecdh_secret, ecdh_ciphertext) =
1830 Backend::x448_generate_key()?;
1831 let ecdh_keyshare = Backend::x448_shared_point(
1832 &ecdh_secret, ecdh_public)?;
1833
1834 let (mlkem_ciphertext, mlkem_keyshare) =
1835 Backend::mlkem1024_encapsulate(mlkem_public)?;
1836
1837 let kek = crate::crypto::asymmetric::multi_key_combine(
1838 &mlkem_keyshare,
1839 &ecdh_keyshare,
1840 ecdh_ciphertext.as_ref(),
1841 ecdh_public.as_ref(),
1842 PublicKeyAlgorithm::MLKEM1024_X448)?;
1843
1844 let esk = aes_key_wrap(SymmetricAlgorithm::AES256,
1845 kek.as_protected(),
1846 data.as_protected())?.into();
1847 Ok(mpi::Ciphertext::MLKEM1024_X448 {
1848 ecdh: Box::new(ecdh_ciphertext),
1849 mlkem: mlkem_ciphertext,
1850 esk,
1851 })
1852 } else {
1853 Err(Error::MalformedPacket(format!(
1854 "Key: Expected MLKEM1024_X448 public key, got {:?}",
1855 self.mpis())).into())
1856 },
1857
1858 RSASign | DSA | ECDSA | EdDSA | Ed25519 | Ed448
1859 | MLDSA65_Ed25519 | MLDSA87_Ed448
1860 | SLHDSA128s | SLHDSA128f | SLHDSA256s =>
1861 Err(Error::InvalidOperation(
1862 format!("{} is not an encryption algorithm", self.pk_algo())
1863 ).into()),
1864
1865 ECDH if matches!(self.mpis(),
1866 PublicKey::ECDH { curve: Curve::Cv25519, ..}) =>
1867 {
1868 let q = match self.mpis() {
1869 PublicKey::ECDH { q, .. } => q,
1870 _ => unreachable!(),
1871 };
1872
1873 // Obtain the authenticated recipient public key R
1874 let R = q.decode_point(&Curve::Cv25519)?.0;
1875
1876 // Generate an ephemeral key pair {v, V=vG}
1877 // Compute the public key.
1878 let (v, VB) = Backend::x25519_generate_key()?;
1879 let VB = mpi::MPI::new_compressed_point(&VB);
1880
1881 // Compute the shared point S = vR;
1882 let S = Backend::x25519_shared_point(&v, R.try_into()?)?;
1883
1884 crate::crypto::ecdh::encrypt_wrap(
1885 self.parts_as_public().role_as_subordinate(), data, VB, &S)
1886 },
1887
1888 RSAEncryptSign | RSAEncrypt |
1889 ElGamalEncrypt | ElGamalEncryptSign |
1890 ECDH |
1891 Private(_) | Unknown(_) => self.encrypt_backend(data),
1892 }
1893 }
1894
1895 /// Verifies the given signature.
1896 pub fn verify(&self, sig: &mpi::Signature, hash_algo: HashAlgorithm,
1897 digest: &[u8]) -> Result<()> {
1898 use crate::crypto::backend::{Backend, interface::Asymmetric};
1899 use crate::crypto::mpi::{PublicKey, Signature};
1900
1901 fn bad(e: impl ToString) -> anyhow::Error {
1902 Error::BadSignature(e.to_string()).into()
1903 }
1904
1905 let ok = match (self.mpis(), sig) {
1906 (PublicKey::Ed25519 { a }, Signature::Ed25519 { s }) =>
1907 Backend::ed25519_verify(a, digest, s)?,
1908
1909 (PublicKey::Ed448 { a }, Signature::Ed448 { s }) =>
1910 Backend::ed448_verify(a, digest, s)?,
1911
1912 (PublicKey::EdDSA { curve, q }, Signature::EdDSA { r, s }) =>
1913 match curve {
1914 Curve::Ed25519 => {
1915 let (public, ..) = q.decode_point(&Curve::Ed25519)?;
1916 assert_eq!(public.len(), 32);
1917
1918 // OpenPGP encodes R and S separately, but our
1919 // cryptographic backends expect them to be
1920 // concatenated.
1921 let mut signature = Vec::with_capacity(64);
1922
1923 // We need to zero-pad them at the front, because
1924 // the MPI encoding drops leading zero bytes.
1925 signature.extend_from_slice(
1926 &r.value_padded(32).map_err(bad)?);
1927 signature.extend_from_slice(
1928 &s.value_padded(32).map_err(bad)?);
1929
1930 // Let's see if we got it right.
1931 debug_assert_eq!(signature.len(), 64);
1932
1933 Backend::ed25519_verify(public.try_into()?,
1934 digest,
1935 &signature.as_slice().try_into()?)?
1936 },
1937 _ => return
1938 Err(Error::UnsupportedEllipticCurve(curve.clone()).into()),
1939 },
1940
1941 (PublicKey::MLDSA65_Ed25519 { eddsa: eddsa_pub, mldsa: mldsa_pub },
1942 Signature::MLDSA65_Ed25519 { eddsa: eddsa_sig, mldsa: mldsa_sig })
1943 => {
1944 let mut ok = 0;
1945
1946 if let Ok(true) = Backend::ed25519_verify(
1947 eddsa_pub, digest, eddsa_sig)
1948 {
1949 ok += 1;
1950 }
1951
1952 if let Ok(true) = Backend::mldsa65_verify(
1953 mldsa_pub, digest, mldsa_sig)
1954 {
1955 ok += 1;
1956 }
1957
1958 ok == 2
1959 },
1960
1961 (PublicKey::MLDSA87_Ed448 { eddsa: eddsa_pub, mldsa: mldsa_pub },
1962 Signature::MLDSA87_Ed448 { eddsa: eddsa_sig, mldsa: mldsa_sig })
1963 => {
1964 let mut ok = 0;
1965
1966 if let Ok(true) = Backend::ed448_verify(
1967 eddsa_pub, digest, eddsa_sig)
1968 {
1969 ok += 1;
1970 }
1971
1972 if let Ok(true) = Backend::mldsa87_verify(
1973 mldsa_pub, digest, mldsa_sig)
1974 {
1975 ok += 1;
1976 }
1977
1978 ok == 2
1979 },
1980
1981 (PublicKey::SLHDSA128s { public }, Signature::SLHDSA128s { sig }) =>
1982 Backend::slhdsa128s_verify(public, digest, sig)?,
1983
1984 (PublicKey::SLHDSA128f { public }, Signature::SLHDSA128f { sig }) =>
1985 Backend::slhdsa128f_verify(public, digest, sig)?,
1986
1987 (PublicKey::SLHDSA256s { public }, Signature::SLHDSA256s { sig }) =>
1988 Backend::slhdsa256s_verify(public, digest, sig)?,
1989
1990 (PublicKey::DSA { p, q, g, y }, Signature::DSA { r, s }) =>
1991 Backend::dsa_verify(p, q, g, y, digest, r, s)?,
1992
1993 (PublicKey::RSA { .. }, Signature::RSA { .. }) |
1994 (PublicKey::ECDSA { .. }, Signature::ECDSA { .. }) =>
1995 return self.verify_backend(sig, hash_algo, digest),
1996
1997 _ => return Err(Error::MalformedPacket(format!(
1998 "unsupported combination of key {} and signature {:?}.",
1999 self.pk_algo(), sig)).into()),
2000 };
2001
2002 if ok {
2003 Ok(())
2004 } else {
2005 Err(Error::ManipulatedMessage.into())
2006 }
2007 }
2008}
2009
2010/// Holds secret key material.
2011///
2012/// This type allows postponing the decryption of the secret key
2013/// material until it is actually needed.
2014///
2015/// If the secret key material is not encrypted with a password, then
2016/// we encrypt it in memory. This helps protect against
2017/// [heartbleed]-style attacks where a buffer over-read allows an
2018/// attacker to read from the process's address space. This
2019/// protection is less important for Rust programs, which are memory
2020/// safe. However, it is essential when Sequoia is used via its FFI.
2021///
2022/// See [`crypto::mem::Encrypted`] for details.
2023///
2024/// [heartbleed]: https://en.wikipedia.org/wiki/Heartbleed
2025/// [`crypto::mem::Encrypted`]: super::super::crypto::mem::Encrypted
2026#[derive(PartialEq, Eq, Hash, Clone, Debug)]
2027pub enum SecretKeyMaterial {
2028 /// Unencrypted secret key. Can be used as-is.
2029 Unencrypted(Unencrypted),
2030 /// The secret key is encrypted with a password.
2031 Encrypted(Encrypted),
2032}
2033
2034assert_send_and_sync!(SecretKeyMaterial);
2035
2036impl From<mpi::SecretKeyMaterial> for SecretKeyMaterial {
2037 fn from(mpis: mpi::SecretKeyMaterial) -> Self {
2038 SecretKeyMaterial::Unencrypted(mpis.into())
2039 }
2040}
2041
2042impl From<Unencrypted> for SecretKeyMaterial {
2043 fn from(key: Unencrypted) -> Self {
2044 SecretKeyMaterial::Unencrypted(key)
2045 }
2046}
2047
2048impl From<Encrypted> for SecretKeyMaterial {
2049 fn from(key: Encrypted) -> Self {
2050 SecretKeyMaterial::Encrypted(key)
2051 }
2052}
2053
2054impl SecretKeyMaterial {
2055 /// Decrypts the secret key material using `password`.
2056 ///
2057 /// The `SecretKeyMaterial` type does not know what kind of key it
2058 /// contains. So, in order to know how many MPIs to parse, the
2059 /// public key algorithm needs to be provided explicitly.
2060 ///
2061 /// This returns an error if the secret key material is not
2062 /// encrypted or the password is incorrect.
2063 pub fn decrypt<P, R>(mut self,
2064 key: &Key<P, R>,
2065 password: &Password)
2066 -> Result<Self>
2067 where
2068 P: KeyParts,
2069 R: KeyRole,
2070 {
2071 self.decrypt_in_place(key, password)?;
2072 Ok(self)
2073 }
2074
2075 /// Decrypts the secret key material using `password`.
2076 ///
2077 /// The `SecretKeyMaterial` type does not know what kind of key it
2078 /// contains. So, in order to know how many MPIs to parse, the
2079 /// public key algorithm needs to be provided explicitly.
2080 ///
2081 /// This returns an error if the secret key material is not
2082 /// encrypted or the password is incorrect.
2083 pub fn decrypt_in_place<P, R>(&mut self,
2084 key: &Key<P, R>,
2085 password: &Password)
2086 -> Result<()>
2087 where
2088 P: KeyParts,
2089 R: KeyRole,
2090 {
2091 match self {
2092 SecretKeyMaterial::Encrypted(e) => {
2093 *self = e.decrypt(key, password)?.into();
2094 Ok(())
2095 }
2096 SecretKeyMaterial::Unencrypted(_) =>
2097 Err(Error::InvalidArgument(
2098 "secret key is not encrypted".into()).into()),
2099 }
2100 }
2101
2102 /// Encrypts the secret key material using `password`.
2103 ///
2104 /// This returns an error if the secret key material is encrypted.
2105 ///
2106 /// See [`Unencrypted::encrypt`] for details.
2107 pub fn encrypt<P, R>(mut self,
2108 key: &Key<P, R>,
2109 password: &Password)
2110 -> Result<Self>
2111 where
2112 P: KeyParts,
2113 R: KeyRole,
2114 {
2115 self.encrypt_in_place(key, password)?;
2116 Ok(self)
2117 }
2118
2119 /// Encrypts the secret key material using `password` with the
2120 /// given parameters.
2121 ///
2122 /// This returns an error if the secret key material is encrypted.
2123 ///
2124 /// See [`Unencrypted::encrypt_with`] for details.
2125 pub fn encrypt_with<P, R>(mut self,
2126 key: &Key<P, R>,
2127 s2k: S2K,
2128 symm: SymmetricAlgorithm,
2129 aead: Option<AEADAlgorithm>,
2130 password: &Password)
2131 -> Result<Self>
2132 where
2133 P: KeyParts,
2134 R: KeyRole,
2135 {
2136 self.encrypt_in_place_with(key, s2k, symm, aead, password)?;
2137 Ok(self)
2138 }
2139
2140 /// Encrypts the secret key material using `password`.
2141 ///
2142 /// This returns an error if the secret key material is encrypted.
2143 ///
2144 /// See [`Unencrypted::encrypt`] for details.
2145 pub fn encrypt_in_place<P, R>(&mut self,
2146 key: &Key<P, R>,
2147 password: &Password)
2148 -> Result<()>
2149 where
2150 P: KeyParts,
2151 R: KeyRole,
2152 {
2153 match self {
2154 SecretKeyMaterial::Unencrypted(ref u) => {
2155 *self = SecretKeyMaterial::Encrypted(
2156 u.encrypt(key, password)?);
2157 Ok(())
2158 }
2159 SecretKeyMaterial::Encrypted(_) =>
2160 Err(Error::InvalidArgument(
2161 "secret key is encrypted".into()).into()),
2162 }
2163 }
2164
2165 /// Encrypts the secret key material using `password` and the
2166 /// given parameters.
2167 ///
2168 /// This returns an error if the secret key material is encrypted.
2169 ///
2170 /// See [`Unencrypted::encrypt`] for details.
2171 pub fn encrypt_in_place_with<P, R>(&mut self,
2172 key: &Key<P, R>,
2173 s2k: S2K,
2174 symm: SymmetricAlgorithm,
2175 aead: Option<AEADAlgorithm>,
2176 password: &Password)
2177 -> Result<()>
2178 where
2179 P: KeyParts,
2180 R: KeyRole,
2181 {
2182 match self {
2183 SecretKeyMaterial::Unencrypted(ref u) => {
2184 *self = SecretKeyMaterial::Encrypted(
2185 u.encrypt_with(key, s2k, symm, aead, password)?);
2186 Ok(())
2187 }
2188 SecretKeyMaterial::Encrypted(_) =>
2189 Err(Error::InvalidArgument(
2190 "secret key is encrypted".into()).into()),
2191 }
2192 }
2193
2194 /// Returns whether the secret key material is encrypted.
2195 pub fn is_encrypted(&self) -> bool {
2196 match self {
2197 SecretKeyMaterial::Encrypted(_) => true,
2198 SecretKeyMaterial::Unencrypted(_) => false,
2199 }
2200 }
2201}
2202
2203/// Unencrypted secret key material.
2204///
2205/// This data structure is used by the [`SecretKeyMaterial`] enum.
2206///
2207/// Unlike an [`Encrypted`] key, this key can be used as-is.
2208///
2209/// The secret key is encrypted in memory and only decrypted on
2210/// demand. This helps protect against [heartbleed]-style
2211/// attacks where a buffer over-read allows an attacker to read from
2212/// the process's address space. This protection is less important
2213/// for Rust programs, which are memory safe. However, it is
2214/// essential when Sequoia is used via its FFI.
2215///
2216/// See [`crypto::mem::Encrypted`] for details.
2217///
2218/// [heartbleed]: https://en.wikipedia.org/wiki/Heartbleed
2219/// [`crypto::mem::Encrypted`]: super::super::crypto::mem::Encrypted
2220// Note: PartialEq, Eq, and Hash on mem::Encrypted does the right
2221// thing.
2222#[derive(Clone, Debug, PartialEq, Eq, Hash)]
2223pub struct Unencrypted {
2224 /// MPIs of the secret key.
2225 mpis: mem::Encrypted,
2226}
2227
2228assert_send_and_sync!(Unencrypted);
2229
2230impl From<mpi::SecretKeyMaterial> for Unencrypted {
2231 fn from(mpis: mpi::SecretKeyMaterial) -> Self {
2232 use crate::serialize::MarshalInto;
2233 // We need to store the type.
2234 let mut plaintext = mem::Protected::new(1 + mpis.serialized_len());
2235 plaintext[0] =
2236 mpis.algo().unwrap_or(PublicKeyAlgorithm::Unknown(0)).into();
2237
2238 mpis.serialize_into(&mut plaintext[1..])
2239 .expect("MPI serialization to vec failed");
2240 Unencrypted {
2241 mpis: mem::Encrypted::new(plaintext)
2242 .expect("encrypting memory failed"),
2243 }
2244 }
2245}
2246
2247impl Unencrypted {
2248 /// Maps the given function over the secret.
2249 pub fn map<F, T>(&self, fun: F) -> T
2250 where F: FnOnce(&mpi::SecretKeyMaterial) -> T
2251 {
2252 self.mpis.map(|plaintext| {
2253 let algo: PublicKeyAlgorithm = plaintext[0].into();
2254 let mpis = mpi::SecretKeyMaterial::from_bytes(algo, &plaintext[1..])
2255 .expect("Decrypted secret key is malformed");
2256 fun(&mpis)
2257 })
2258 }
2259
2260 /// Encrypts the secret key material using `password`.
2261 ///
2262 /// This encrypts the secret key material using AES-128/OCB and a
2263 /// key derived from the `password` using the default [`S2K`]
2264 /// scheme.
2265 pub fn encrypt<P, R>(&self,
2266 key: &Key<P, R>,
2267 password: &Password)
2268 -> Result<Encrypted>
2269 where
2270 P: KeyParts,
2271 R: KeyRole,
2272 {
2273 // Pick sensible parameters according to the key version.
2274 let (s2k, symm, aead) = match key.version() {
2275 6 => (
2276 S2K::default(),
2277 SymmetricAlgorithm::AES128,
2278 Some(AEADAlgorithm::OCB),
2279 ),
2280
2281 _ => (
2282 S2K::default(),
2283 SymmetricAlgorithm::default(),
2284 None,
2285 ),
2286 };
2287
2288 self.encrypt_with(key, s2k, symm, aead, password)
2289 }
2290
2291 /// Encrypts the secret key material using `password` and the
2292 /// given parameters.
2293 pub fn encrypt_with<P, R>(&self,
2294 key: &Key<P, R>,
2295 s2k: S2K,
2296 symm: SymmetricAlgorithm,
2297 aead: Option<AEADAlgorithm>,
2298 password: &Password)
2299 -> Result<Encrypted>
2300 where
2301 P: KeyParts,
2302 R: KeyRole,
2303 {
2304 use std::io::Write;
2305 use crate::crypto::symmetric::Encryptor;
2306
2307 let derived_key = s2k.derive_key(password, symm.key_size()?)?;
2308 let checksum = Default::default();
2309
2310 constrain_encryption_methods(key, &s2k, symm, aead, Some(checksum))?;
2311
2312 if matches!(s2k, S2K::Argon2 { .. }) && aead.is_none() {
2313 return Err(Error::InvalidOperation(
2314 "Argon2 MUST be used with an AEAD mode".into()).into());
2315 }
2316
2317 if let Some(aead) = aead {
2318 use crate::serialize::MarshalInto;
2319
2320 let mut iv = vec![0; aead.nonce_size()?];
2321 crypto::random(&mut iv)?;
2322
2323 let schedule = Key253Schedule::new(
2324 match key.role() {
2325 KeyRoleRT::Primary => Tag::SecretKey,
2326 KeyRoleRT::Subordinate => Tag::SecretSubkey,
2327 KeyRoleRT::Unspecified =>
2328 return Err(Error::InvalidOperation(
2329 "cannot encrypt key with unspecified role".into()).into()),
2330 },
2331 key.parts_as_public(), derived_key, symm, aead, &iv)?;
2332 let mut enc = schedule.encryptor()?;
2333
2334 // Encrypt the secret key.
2335 let esk = self.map(|mpis| -> Result<Vec<u8>> {
2336 let mut esk =
2337 vec![0; mpis.serialized_len() + aead.digest_size()?];
2338 let secret = mpis.to_vec()?;
2339 enc.encrypt_seal(&mut esk, &secret)?;
2340 Ok(esk)
2341 })?;
2342
2343 Ok(Encrypted::new_aead(s2k, symm, aead, iv.into_boxed_slice(),
2344 esk.into_boxed_slice()))
2345 } else {
2346 use crypto::symmetric::{
2347 BlockCipherMode,
2348 PaddingMode,
2349 };
2350
2351 // Ciphertext is preceded by a random block.
2352 let mut trash = vec![0u8; symm.block_size()?];
2353 crypto::random(&mut trash)?;
2354
2355 let mut esk = Vec::new();
2356 let mut encryptor =
2357 Encryptor::new(symm, BlockCipherMode::CFB, PaddingMode::None,
2358 &derived_key, None, &mut esk)?;
2359 encryptor.write_all(&trash)?;
2360 self.map(|mpis| mpis.serialize_with_checksum(&mut encryptor,
2361 checksum))?;
2362 drop(encryptor);
2363
2364 Ok(Encrypted::new(s2k, symm, Some(checksum),
2365 esk.into_boxed_slice()))
2366 }
2367 }
2368}
2369
2370/// Secret key material encrypted with a password.
2371///
2372/// This data structure is used by the [`SecretKeyMaterial`] enum.
2373///
2374#[derive(Clone, Debug)]
2375pub struct Encrypted {
2376 /// Key derivation mechanism to use.
2377 s2k: S2K,
2378 /// Symmetric algorithm used to encrypt the secret key material.
2379 algo: SymmetricAlgorithm,
2380 /// AEAD algorithm and IV used to encrypt the secret key material.
2381 aead: Option<(AEADAlgorithm, Box<[u8]>)>,
2382 /// Checksum method.
2383 checksum: Option<mpi::SecretKeyChecksum>,
2384 /// Encrypted MPIs prefixed with the IV.
2385 ///
2386 /// If we recognized the S2K object during parsing, we can
2387 /// successfully parse the data into S2K, IV, and ciphertext.
2388 /// However, if we do not recognize the S2K type, we do not know
2389 /// how large its parameters are, so we cannot cleanly parse it,
2390 /// and have to accept that the S2K's body bleeds into the rest of
2391 /// the data.
2392 ciphertext: std::result::Result<(usize, // IV length
2393 Box<[u8]>), // IV + ciphertext.
2394 Box<[u8]>>, // S2K body + IV + ciphertext.
2395}
2396
2397assert_send_and_sync!(Encrypted);
2398
2399// Because the S2K and ciphertext cannot be cleanly separated at parse
2400// time, we need to carefully compare and hash encrypted key packets.
2401
2402impl PartialEq for Encrypted {
2403 fn eq(&self, other: &Encrypted) -> bool {
2404 self.algo == other.algo
2405 && self.aead == other.aead
2406 && self.checksum == other.checksum
2407 && match (&self.ciphertext, &other.ciphertext) {
2408 (Ok(a), Ok(b)) =>
2409 self.s2k == other.s2k && a == b,
2410 (Err(a_raw), Err(b_raw)) => {
2411 // Treat S2K and ciphertext as opaque blob.
2412 // XXX: This would be nicer without the allocations.
2413 use crate::serialize::MarshalInto;
2414 let mut a = self.s2k.to_vec().unwrap();
2415 let mut b = other.s2k.to_vec().unwrap();
2416 a.extend_from_slice(a_raw);
2417 b.extend_from_slice(b_raw);
2418 a == b
2419 },
2420 _ => false,
2421 }
2422 }
2423}
2424
2425impl Eq for Encrypted {}
2426
2427impl std::hash::Hash for Encrypted {
2428 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2429 self.algo.hash(state);
2430 self.aead.hash(state);
2431 self.checksum.hash(state);
2432 match &self.ciphertext {
2433 Ok(c) => {
2434 self.s2k.hash(state);
2435 c.hash(state);
2436 },
2437 Err(c) => {
2438 // Treat S2K and ciphertext as opaque blob.
2439 // XXX: This would be nicer without the allocations.
2440 use crate::serialize::MarshalInto;
2441 let mut a = self.s2k.to_vec().unwrap();
2442 a.extend_from_slice(c);
2443 a.hash(state);
2444 },
2445 }
2446 }
2447}
2448
2449impl Encrypted {
2450 /// Creates a new encrypted key object.
2451 pub fn new(s2k: S2K, algo: SymmetricAlgorithm,
2452 checksum: Option<mpi::SecretKeyChecksum>, ciphertext: Box<[u8]>)
2453 -> Self
2454 {
2455 Self::new_raw(s2k, algo, checksum, Ok((0, ciphertext)))
2456 }
2457
2458 /// Creates a new encrypted key object.
2459 pub fn new_aead(s2k: S2K,
2460 sym_algo: SymmetricAlgorithm,
2461 aead_algo: AEADAlgorithm,
2462 aead_iv: Box<[u8]>,
2463 ciphertext: Box<[u8]>)
2464 -> Self
2465 {
2466 Encrypted {
2467 s2k,
2468 algo: sym_algo,
2469 aead: Some((aead_algo, aead_iv)),
2470 checksum: None,
2471 ciphertext: Ok((0, ciphertext)),
2472 }
2473 }
2474
2475 /// Creates a new encrypted key object.
2476 pub(crate) fn new_raw(s2k: S2K, algo: SymmetricAlgorithm,
2477 checksum: Option<mpi::SecretKeyChecksum>,
2478 ciphertext: std::result::Result<(usize, Box<[u8]>),
2479 Box<[u8]>>)
2480 -> Self
2481 {
2482 Encrypted { s2k, algo, aead: None, checksum, ciphertext }
2483 }
2484
2485 /// Returns the key derivation mechanism.
2486 pub fn s2k(&self) -> &S2K {
2487 &self.s2k
2488 }
2489
2490 /// Returns the symmetric algorithm used to encrypt the secret
2491 /// key material.
2492 pub fn algo(&self) -> SymmetricAlgorithm {
2493 self.algo
2494 }
2495
2496 /// Returns the AEAD algorithm used to encrypt the secret key
2497 /// material.
2498 pub fn aead_algo(&self) -> Option<AEADAlgorithm> {
2499 self.aead.as_ref().map(|(a, _iv)| *a)
2500 }
2501
2502 /// Returns the AEAD IV used to encrypt the secret key material.
2503 pub fn aead_iv(&self) -> Option<&[u8]> {
2504 self.aead.as_ref().map(|(_a, iv)| &iv[..])
2505 }
2506
2507 /// Returns the checksum method used to protect the encrypted
2508 /// secret key material, if any.
2509 pub fn checksum(&self) -> Option<mpi::SecretKeyChecksum> {
2510 self.checksum
2511 }
2512
2513 /// Returns the encrypted secret key material.
2514 ///
2515 /// If the [`S2K`] mechanism is not supported by Sequoia, this
2516 /// function will fail. Note that the information is not lost,
2517 /// but stored in the packet. If the packet is serialized again,
2518 /// it is written out.
2519 ///
2520 /// [`S2K`]: super::super::crypto::S2K
2521 pub fn ciphertext(&self) -> Result<&[u8]> {
2522 self.ciphertext
2523 .as_ref()
2524 .map(|(_cfb_iv_len, ciphertext)| &ciphertext[..])
2525 .map_err(|_| Error::MalformedPacket(
2526 format!("Unknown S2K: {:?}", self.s2k)).into())
2527 }
2528
2529 /// Returns the encrypted secret key material, possibly including
2530 /// the body of the S2K object.
2531 pub(crate) fn raw_ciphertext(&self) -> &[u8] {
2532 match self.ciphertext.as_ref() {
2533 Ok((_cfb_iv_len, ciphertext)) => &ciphertext[..],
2534 Err(s2k_ciphertext) => &s2k_ciphertext[..],
2535 }
2536 }
2537
2538 /// Returns the length of the CFB IV, if used.
2539 ///
2540 /// In v6 key packets, we explicitly model the length of the IV,
2541 /// but in Sequoia we store the IV and the ciphertext as one
2542 /// block, due to how bad this was modeled in v4 key packets.
2543 /// However, now that our in-core representation is less precise
2544 /// to support v4, we need to track this length to uphold our
2545 /// equality guarantee.
2546 pub(crate) fn cfb_iv_len(&self) -> usize {
2547 self.ciphertext.as_ref().ok()
2548 .map(|(cfb_iv_len, _)| *cfb_iv_len)
2549 .unwrap_or(0)
2550 }
2551
2552 /// Decrypts the secret key material using `password`.
2553 ///
2554 /// The `Encrypted` key does not know what kind of key it is, so
2555 /// the public key algorithm is needed to parse the correct number
2556 /// of MPIs.
2557 pub fn decrypt<P, R>(&self, key: &Key<P, R>, password: &Password)
2558 -> Result<Unencrypted>
2559 where
2560 P: KeyParts,
2561 R: KeyRole,
2562 {
2563 use std::io::Read;
2564 use crate::crypto;
2565
2566 constrain_encryption_methods(
2567 key, &self.s2k, self.algo,self.aead.as_ref().map(|(a, _)| *a),
2568 self.checksum)?;
2569
2570 let derived_key = self.s2k.derive_key(password, self.algo.key_size()?)?;
2571 let ciphertext = self.ciphertext()?;
2572
2573 if let Some((aead, iv)) = &self.aead {
2574 let schedule = Key253Schedule::new(
2575 match key.role() {
2576 KeyRoleRT::Primary => Tag::SecretKey,
2577 KeyRoleRT::Subordinate => Tag::SecretSubkey,
2578 KeyRoleRT::Unspecified =>
2579 return Err(Error::InvalidOperation(
2580 "cannot decrypt key with unspecified role".into()).into()),
2581 },
2582 key.parts_as_public(), derived_key, self.algo, *aead, iv)?;
2583 let mut dec = schedule.decryptor()?;
2584
2585 // Read the secret key.
2586 let mut secret = mem::Protected::new(
2587 ciphertext.len().saturating_sub(aead.digest_size()?));
2588 dec.decrypt_verify(&mut secret, ciphertext)?;
2589
2590 mpi::SecretKeyMaterial::from_bytes(
2591 key.pk_algo(), &secret).map(|m| m.into())
2592 } else {
2593 use crypto::symmetric::{
2594 BlockCipherMode,
2595 UnpaddingMode,
2596 };
2597
2598 let cur = buffered_reader::Memory::with_cookie(
2599 ciphertext, Default::default());
2600 let mut dec =
2601 crypto::symmetric::InternalDecryptor::new(
2602 self.algo,
2603 BlockCipherMode::CFB,
2604 UnpaddingMode::None,
2605 &derived_key,
2606 None,
2607 cur)?;
2608
2609 // Consume the first block.
2610 let block_size = self.algo.block_size()?;
2611 let mut trash = mem::Protected::new(block_size);
2612 dec.read_exact(&mut trash)?;
2613
2614 // Read the secret key.
2615 let mut secret = mem::Protected::new(ciphertext.len() - block_size);
2616 dec.read_exact(&mut secret)?;
2617
2618 mpi::SecretKeyMaterial::from_bytes_with_checksum(
2619 key.pk_algo(), &secret, self.checksum.unwrap_or_default())
2620 .map(|m| m.into())
2621 }
2622 }
2623}
2624
2625/// Constrains the secret key material encryption methods according to
2626/// [Section 3.7.2.1. of RFC 9580].
2627///
2628/// [Section 3.7.2.1. of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-3.7.2.1
2629fn constrain_encryption_methods<P, R>(key: &Key<P, R>,
2630 s2k: &S2K,
2631 _symm: SymmetricAlgorithm,
2632 aead: Option<AEADAlgorithm>,
2633 checksum: Option<mpi::SecretKeyChecksum>)
2634 -> Result<()>
2635where
2636 P: KeyParts,
2637 R: KeyRole,
2638{
2639 #[allow(deprecated)]
2640 match s2k {
2641 S2K::Argon2 { .. } if aead.is_none() =>
2642 Err(Error::InvalidOperation(
2643 "Argon2 MUST be used with an AEAD mode".into()).into()),
2644
2645 S2K::Implicit if key.version() == 6 =>
2646 Err(Error::InvalidOperation(
2647 "Implicit S2K MUST NOT be used with v6 keys".into()).into()),
2648
2649 // Technically not forbidden, but this is a terrible idea and
2650 // I doubt that anyone depends on it. Let's see whether we
2651 // can get away with being strict here.
2652 S2K::Simple { .. } if key.version() == 6 =>
2653 Err(Error::InvalidOperation(
2654 "Simple S2K SHOULD NOT be used with v6 keys".into()).into()),
2655
2656 _ if key.version() == 6 && aead.is_none()
2657 && checksum != Some(mpi::SecretKeyChecksum::SHA1) =>
2658 Err(Error::InvalidOperation(
2659 "Malleable CFB MUST NOT be used with v6 keys".into()).into()),
2660
2661 _ => Ok(()),
2662 }
2663}
2664
2665pub(crate) struct Key253Schedule<'a> {
2666 symm: SymmetricAlgorithm,
2667 aead: AEADAlgorithm,
2668 nonce: &'a [u8],
2669 kek: SessionKey,
2670 ad: Vec<u8>
2671}
2672
2673impl<'a> Key253Schedule<'a> {
2674 fn new<R>(tag: Tag,
2675 key: &Key<PublicParts, R>,
2676 derived_key: SessionKey,
2677 symm: SymmetricAlgorithm,
2678 aead: AEADAlgorithm,
2679 nonce: &'a [u8])
2680 -> Result<Self>
2681 where
2682 R: KeyRole,
2683 {
2684 use crate::serialize::{Marshal, MarshalInto};
2685 use crate::crypto::backend::{Backend, interface::Kdf};
2686
2687 let info = [
2688 0b1100_0000 | u8::from(tag), // Canonicalized packet type.
2689 key.version(),
2690 symm.into(),
2691 aead.into(),
2692 ];
2693 let mut kek = vec![0; symm.key_size()?].into();
2694 Backend::hkdf_sha256(&derived_key, None, &info, &mut kek)?;
2695
2696 let mut ad = Vec::with_capacity(key.serialized_len());
2697 ad.push(0b1100_0000 | u8::from(tag)); // Canonicalized packet type.
2698 key.serialize(&mut ad)?;
2699
2700 Ok(Self {
2701 symm,
2702 aead,
2703 nonce,
2704 kek,
2705 ad,
2706 })
2707 }
2708
2709 fn decryptor(&self) -> Result<crypto::aead::DecryptionContext> {
2710 self.aead.context(self.symm, &self.kek, &self.ad, self.nonce)?
2711 .for_decryption()
2712 }
2713
2714 fn encryptor(&self) -> Result<crypto::aead::EncryptionContext> {
2715 self.aead.context(self.symm, &self.kek, &self.ad, self.nonce)?
2716 .for_encryption()
2717 }
2718}
2719
2720#[cfg(test)]
2721mod tests {
2722 use crate::packet::Key;
2723 use crate::Cert;
2724 use crate::packet::key::SecretKeyMaterial;
2725 use crate::packet::Packet;
2726 use super::*;
2727 use crate::parse::Parse;
2728 use crate::SignatureType;
2729 use crate::crypto::mpi::PublicKey;
2730
2731 #[test]
2732 fn encrypted_rsa_key() {
2733 let cert = Cert::from_bytes(
2734 crate::tests::key("testy-new-encrypted-with-123.pgp")).unwrap();
2735 let key = cert.primary_key().key().clone();
2736 let (key, secret) = key.take_secret();
2737 let mut secret = secret.unwrap();
2738
2739 assert!(secret.is_encrypted());
2740 secret.decrypt_in_place(&key, &"123".into()).unwrap();
2741 assert!(!secret.is_encrypted());
2742 let (pair, _) = key.add_secret(secret);
2743 assert!(pair.has_unencrypted_secret());
2744
2745 match pair.secret() {
2746 SecretKeyMaterial::Unencrypted(ref u) => u.map(|mpis| match mpis {
2747 mpi::SecretKeyMaterial::RSA { .. } => (),
2748 _ => panic!(),
2749 }),
2750 _ => panic!(),
2751 }
2752 }
2753
2754 #[test]
2755 fn signature_roundtrip() {
2756 let gen_v4_rsa = |bits: usize| -> Key<key::SecretParts, key::PrimaryRole> {
2757 Key4::generate_rsa(bits)
2758 .expect("Can generate a v4 RSA key")
2759 .into()
2760 };
2761 let gen_v6_rsa = |bits: usize| -> Key<_, _> {
2762 Key6::generate_rsa(bits)
2763 .expect("Can generate a v6 RSA key")
2764 .into()
2765 };
2766 // Disabled: see below.
2767 //let gen_v4_dsa = |bits: usize| -> Key<_, _> {
2768 // Key4::generate_dsa(bits)
2769 // .expect("Can generate a v4 DSA key")
2770 // .into()
2771 //};
2772 let gen_v4_curve = |curve: Curve| -> Key<_, _> {
2773 Key4::generate_ecc(true, curve.clone())
2774 .unwrap_or_else(|_| panic!("Can generate a v4 {:?}", curve))
2775 .into()
2776 };
2777 let gen_v6_curve = |curve: Curve| -> Key<_, _> {
2778 Key6::generate_ecc(true, curve.clone())
2779 .unwrap_or_else(|_| panic!("Can generate a v6 {:?}", curve))
2780 .into()
2781 };
2782 let gen_v4_ed25519 = || -> Key<_, _> {
2783 Key4::generate_ed25519()
2784 .expect("Can generate a v4 Ed25519 key")
2785 .into()
2786 };
2787 let gen_v6_ed25519 = || -> Key<_, _> {
2788 Key6::generate_ed25519()
2789 .expect("Can generate a v6 Ed25519 key")
2790 .into()
2791 };
2792 let gen_v4_ed448 = || -> Key<_, _> {
2793 Key4::generate_ed448()
2794 .expect("Can generate a v4 Ed448 key")
2795 .into()
2796 };
2797 let gen_v6_ed448 = || -> Key<_, _> {
2798 Key6::generate_ed448()
2799 .expect("Can generate a v6 Ed448 key")
2800 .into()
2801 };
2802 let gen_v6_mldsa65_ed25519 = || -> Key<_, _> {
2803 Key6::generate_mldsa65_ed25519()
2804 .expect("Can generate a v6 ML-DSA-65+Ed25519 key")
2805 .into()
2806 };
2807 let gen_v6_mldsa87_ed448 = || -> Key<_, _> {
2808 Key6::generate_mldsa87_ed448()
2809 .expect("Can generate a v6 ML-DSA-87+Ed448 key")
2810 .into()
2811 };
2812 let gen_v6_slhdsa128s = || -> Key<_, _> {
2813 Key6::generate_slhdsa128s()
2814 .expect("Can generate a v6 SLH-DSA-128s key")
2815 .into()
2816 };
2817 let gen_v6_slhdsa128f = || -> Key<_, _> {
2818 Key6::generate_slhdsa128f()
2819 .expect("Can generate a v6 SLH-DSA-128f key")
2820 .into()
2821 };
2822 let gen_v6_slhdsa256s = || -> Key<_, _> {
2823 Key6::generate_slhdsa256s()
2824 .expect("Can generate a v6 SLH-DSA-256s key")
2825 .into()
2826 };
2827
2828 #[allow(deprecated)]
2829 for (algo, curve, profile, gen) in [
2830 // RSA
2831 (PublicKeyAlgorithm::RSAEncryptSign, None, 4,
2832 Box::new(|| gen_v4_rsa(2048)) as Box<dyn Fn () -> _>),
2833 (PublicKeyAlgorithm::RSAEncryptSign, None, 4,
2834 Box::new(|| gen_v4_rsa(3072)) as Box<dyn Fn () -> _>),
2835 (PublicKeyAlgorithm::RSAEncryptSign, None, 4,
2836 Box::new(|| gen_v4_rsa(4096)) as Box<dyn Fn () -> _>),
2837 (PublicKeyAlgorithm::RSAEncryptSign, None, 6,
2838 Box::new(|| gen_v6_rsa(2048))),
2839 (PublicKeyAlgorithm::RSAEncryptSign, None, 6,
2840 Box::new(|| gen_v6_rsa(3072))),
2841 (PublicKeyAlgorithm::RSAEncryptSign, None, 6,
2842 Box::new(|| gen_v6_rsa(4096))),
2843
2844 // DSA
2845 //
2846 // DSA is deprecated.
2847 //
2848 // Disabled, because DSA generation doesn't work on
2849 // Windows, but PublicKeyAlgorithm::DSA.is_supported()
2850 // returns true. This is because CNG does support signing
2851 // and verification.
2852 //(PublicKeyAlgorithm::DSA, None, 4,
2853 // Box::new(|| gen_v4_dsa(2048)) as Box<dyn Fn () -> _>),
2854 //(PublicKeyAlgorithm::DSA, None, 4,
2855 // Box::new(|| gen_v4_dsa(3072)) as Box<dyn Fn () -> _>),
2856
2857 // EdDSA 25519.
2858 //
2859 // Note: EdDSA Ed25519 is deprecated for v6.
2860 (PublicKeyAlgorithm::EdDSA, Some(Curve::Ed25519), 4,
2861 Box::new(|| gen_v4_curve(Curve::Ed25519))),
2862
2863 // Modern Ed25519.
2864 (PublicKeyAlgorithm::Ed25519, None, 4,
2865 Box::new(gen_v4_ed25519)),
2866 (PublicKeyAlgorithm::Ed25519, None, 6,
2867 Box::new(gen_v6_ed25519)),
2868
2869 // Ed448.
2870 (PublicKeyAlgorithm::Ed448, None, 4,
2871 Box::new(gen_v4_ed448)),
2872 (PublicKeyAlgorithm::Ed448, None, 6,
2873 Box::new(gen_v6_ed448)),
2874
2875 // Nist.
2876 (PublicKeyAlgorithm::ECDSA, Some(Curve::NistP256), 4,
2877 Box::new(|| gen_v4_curve(Curve::NistP256))),
2878 (PublicKeyAlgorithm::ECDSA, Some(Curve::NistP256), 6,
2879 Box::new(|| gen_v6_curve(Curve::NistP256))),
2880 (PublicKeyAlgorithm::ECDSA, Some(Curve::NistP384), 4,
2881 Box::new(|| gen_v4_curve(Curve::NistP384))),
2882 (PublicKeyAlgorithm::ECDSA, Some(Curve::NistP384), 6,
2883 Box::new(|| gen_v6_curve(Curve::NistP384))),
2884 (PublicKeyAlgorithm::ECDSA, Some(Curve::NistP521), 4,
2885 Box::new(|| gen_v4_curve(Curve::NistP521))),
2886 (PublicKeyAlgorithm::ECDSA, Some(Curve::NistP521), 6,
2887 Box::new(|| gen_v6_curve(Curve::NistP521))),
2888
2889 // Brainpool.
2890 (PublicKeyAlgorithm::ECDSA, Some(Curve::BrainpoolP256), 4,
2891 Box::new(|| gen_v4_curve(Curve::BrainpoolP256))),
2892 (PublicKeyAlgorithm::ECDSA, Some(Curve::BrainpoolP256), 6,
2893 Box::new(|| gen_v6_curve(Curve::BrainpoolP256))),
2894 (PublicKeyAlgorithm::ECDSA, Some(Curve::BrainpoolP384), 4,
2895 Box::new(|| gen_v4_curve(Curve::BrainpoolP384))),
2896 (PublicKeyAlgorithm::ECDSA, Some(Curve::BrainpoolP384), 6,
2897 Box::new(|| gen_v6_curve(Curve::BrainpoolP384))),
2898 (PublicKeyAlgorithm::ECDSA, Some(Curve::BrainpoolP512), 4,
2899 Box::new(|| gen_v4_curve(Curve::BrainpoolP512))),
2900 (PublicKeyAlgorithm::ECDSA, Some(Curve::BrainpoolP512), 6,
2901 Box::new(|| gen_v6_curve(Curve::BrainpoolP512))),
2902
2903 // PQC signing algorithms (v6 only).
2904 (PublicKeyAlgorithm::MLDSA65_Ed25519, None, 6,
2905 Box::new(gen_v6_mldsa65_ed25519)),
2906 (PublicKeyAlgorithm::MLDSA87_Ed448, None, 6,
2907 Box::new(gen_v6_mldsa87_ed448)),
2908 (PublicKeyAlgorithm::SLHDSA128s, None, 6,
2909 Box::new(gen_v6_slhdsa128s)),
2910 (PublicKeyAlgorithm::SLHDSA128f, None, 6,
2911 Box::new(gen_v6_slhdsa128f)),
2912 (PublicKeyAlgorithm::SLHDSA256s, None, 6,
2913 Box::new(gen_v6_slhdsa256s)),
2914 ]
2915 {
2916 eprintln!("Checking algo: {}, curve: {:?}, profile: {}.",
2917 algo, curve, profile);
2918 if ! algo.is_supported() {
2919 eprintln!("Algorithm {} not supported, skipping test.",
2920 algo);
2921 continue;
2922 }
2923
2924 if let Some(curve) = curve.as_ref() {
2925 if ! curve.is_supported() {
2926 eprintln!("Curve {:?} not supported, skipping test.",
2927 curve);
2928 continue;
2929 }
2930 }
2931
2932 let key = gen();
2933
2934 // Make sure we got the right type of key.
2935 assert_eq!(algo, key.pk_algo(),
2936 "\n\
2937 algo expected: {:?} ({})\n\
2938 algo got: {:?} ({})",
2939 algo, u8::from(algo),
2940 key.pk_algo(), u8::from(key.pk_algo()));
2941
2942 let got_curve = match key.mpis() {
2943 PublicKey::EdDSA { curve, .. }
2944 | PublicKey::ECDSA { curve, .. }
2945 | PublicKey::ECDH { curve, .. } =>
2946 {
2947 Some(curve.clone())
2948 }
2949 _ => None,
2950 };
2951 assert_eq!(curve, got_curve,
2952 "\n\
2953 curve expected: {:?}\n\
2954 curve got: {:?}",
2955 curve, got_curve);
2956
2957 assert_eq!(profile, key.version(),
2958 "\n\
2959 profile expected: {:?}\n\
2960 profile got: {:?}",
2961 profile, key.version());
2962
2963 let mut pair = key.clone().into_keypair().unwrap();
2964 let hash = HashAlgorithm::default();
2965
2966 // Sign.
2967 let ctx = hash.context().unwrap().for_signature(profile);
2968 let sig = SignatureBuilder::new(SignatureType::Binary)
2969 .sign_hash(&mut pair, ctx).unwrap();
2970
2971 // Verify.
2972 let ctx = hash.context().unwrap().for_signature(profile);
2973 sig.verify_hash(&key, ctx).unwrap();
2974
2975 // Verify that a wrong digest is rejected.
2976 let mut ctx = hash.context().unwrap().for_signature(profile);
2977 ctx.update(b"tampered");
2978 assert!(sig.verify_hash(&key, ctx).is_err(),
2979 "Tampered {:?} v{} signature should be rejected",
2980 algo, profile);
2981 }
2982 }
2983
2984 #[test]
2985 fn primary_key_encrypt_decrypt() -> Result<()> {
2986 key_encrypt_decrypt::<PrimaryRole>()
2987 }
2988
2989 #[test]
2990 fn subkey_encrypt_decrypt() -> Result<()> {
2991 key_encrypt_decrypt::<SubordinateRole>()
2992 }
2993
2994 fn key_encrypt_decrypt<R>() -> Result<()>
2995 where
2996 R: KeyRole + PartialEq,
2997 {
2998 let mut g = quickcheck::Gen::new(256);
2999 let p: Password = Vec::<u8>::arbitrary(&mut g).into();
3000
3001 let check = |key: Key<SecretParts, R>| -> Result<()> {
3002 let encrypted = key.clone().encrypt_secret(&p)?;
3003 let decrypted = encrypted.decrypt_secret(&p)?;
3004 assert_eq!(key, decrypted);
3005 Ok(())
3006 };
3007
3008 use crate::types::Curve::*;
3009 for curve in vec![NistP256, NistP384, NistP521, Ed25519] {
3010 if ! curve.is_supported() {
3011 eprintln!("Skipping unsupported {}", curve);
3012 continue;
3013 }
3014
3015 let key: Key4<_, R>
3016 = Key4::generate_ecc(true, curve.clone())?;
3017 check(key.into())?;
3018
3019 let key: Key6<_, R>
3020 = Key6::generate_ecc(true, curve.clone())?;
3021 check(key.into())?;
3022 }
3023
3024 for bits in vec![2048, 3072] {
3025 if ! PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
3026 eprintln!("Skipping unsupported RSA");
3027 continue;
3028 }
3029
3030 let key: Key4<_, R>
3031 = Key4::generate_rsa(bits)?;
3032 check(key.into())?;
3033
3034 let key: Key6<_, R>
3035 = Key6::generate_rsa(bits)?;
3036 check(key.into())?;
3037 }
3038
3039 Ok(())
3040 }
3041
3042 quickcheck! {
3043 fn roundtrip_public(p: Key<PublicParts, UnspecifiedRole>) -> bool {
3044 use crate::parse::Parse;
3045 use crate::serialize::MarshalInto;
3046 let buf = p.to_vec().expect("Failed to serialize key");
3047 let q = Key::from_bytes(&buf).expect("Failed to parse key").into();
3048 assert_eq!(p, q);
3049 true
3050 }
3051 }
3052
3053 #[test]
3054 fn public_serialization_drops_secret_material() -> Result<()> {
3055 use crate::serialize::Serialize;
3056
3057 let (cert, _) = CertBuilder::new().generate()?;
3058 let pk = cert.primary_key().key();
3059 assert!(pk.has_secret());
3060
3061 let public = pk.parts_as_public();
3062
3063 let mut bytes = Vec::new();
3064 Packet::from(public.clone()).serialize(&mut bytes)?;
3065
3066 let p = Packet::from_bytes(&bytes)?;
3067 match p {
3068 Packet::PublicKey(key) => assert!(!key.has_secret()),
3069 _ => panic!("expected a public key packet"),
3070 }
3071
3072 Ok(())
3073 }
3074
3075 quickcheck! {
3076 fn roundtrip_secret(p: Key<SecretParts, PrimaryRole>) -> bool {
3077 use crate::parse::Parse;
3078 use crate::serialize::MarshalInto;
3079 let buf = p.to_vec().expect("Failed to serialize key");
3080 let q = Key::from_bytes(&buf).expect("Failed to parse key")
3081 .parts_into_secret().expect("No secret material")
3082 .role_into_primary();
3083 assert_eq!(p, q);
3084 true
3085 }
3086 }
3087
3088 #[test]
3089 fn parts_as_public_does_not_remove_secret_material() -> Result<()> {
3090 let (cert, _) = CertBuilder::new().generate()?;
3091 let pk = cert.primary_key().key();
3092 assert!(pk.has_secret());
3093
3094 let sk = pk.parts_as_secret()?;
3095 let public = sk.parts_as_public();
3096
3097 assert!(public.has_secret());
3098 Ok(())
3099 }
3100
3101 fn mutate_eq_discriminates_key<P, R>(key: Key<P, R>, i: usize) -> bool
3102 where P: KeyParts,
3103 R: KeyRole,
3104 Key<P, R>: Into<Packet>,
3105 {
3106 use crate::serialize::MarshalInto;
3107 let p: Packet = key.into();
3108 let mut buf = p.to_vec().unwrap();
3109 // Avoid first two bytes so that we don't change the
3110 // type and reduce the chance of changing the length.
3111 if buf.len() < 3 { return true; }
3112 let bit = i % ((buf.len() - 2) * 8) + 16;
3113 buf[bit / 8] ^= 1 << (bit % 8);
3114 let ok = match Packet::from_bytes(&buf) {
3115 Ok(q) => p != q,
3116 Err(_) => true, // Packet failed to parse.
3117 };
3118 if ! ok {
3119 eprintln!("mutate_eq_discriminates_key for ({:?}, {})", p, i);
3120 }
3121 ok
3122 }
3123
3124 // Given a packet and a position, induces a bit flip in the
3125 // serialized form, then checks that PartialEq detects that.
3126 // Recall that for packets, PartialEq is defined using the
3127 // serialized form.
3128 quickcheck! {
3129 fn mutate_eq_discriminates_pp(key: Key<PublicParts, PrimaryRole>,
3130 i: usize) -> bool {
3131 mutate_eq_discriminates_key(key, i)
3132 }
3133 }
3134 quickcheck! {
3135 fn mutate_eq_discriminates_ps(key: Key<PublicParts, SubordinateRole>,
3136 i: usize) -> bool {
3137 mutate_eq_discriminates_key(key, i)
3138 }
3139 }
3140 quickcheck! {
3141 fn mutate_eq_discriminates_sp(key: Key<SecretParts, PrimaryRole>,
3142 i: usize) -> bool {
3143 mutate_eq_discriminates_key(key, i)
3144 }
3145 }
3146 quickcheck! {
3147 fn mutate_eq_discriminates_ss(key: Key<SecretParts, SubordinateRole>,
3148 i: usize) -> bool {
3149 mutate_eq_discriminates_key(key, i)
3150 }
3151 }
3152}