sequoia_openpgp/packet/skesk.rs
1//! Symmetric-Key Encrypted Session Key Packets.
2//!
3//! SKESK packets hold symmetrically encrypted session keys. The
4//! session key is needed to decrypt the actual ciphertext. See
5//! [Section 5.3 of RFC 9580] for details.
6//!
7//! [Section 5.3 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.3
8
9#[cfg(test)]
10use quickcheck::{Arbitrary, Gen};
11
12use crate::Result;
13use crate::crypto::{
14 Password,
15 SessionKey,
16};
17
18use crate::types::{
19 SymmetricAlgorithm,
20};
21use crate::Packet;
22
23mod v4;
24pub use v4::SKESK4;
25mod v6;
26pub use v6::SKESK6;
27
28/// Holds a symmetrically encrypted session key.
29///
30/// The session key is used to decrypt the actual ciphertext, which is
31/// typically stored in a [SEIP] packet. See [Section 5.3 of RFC
32/// 9580] for details.
33///
34/// An SKESK packet is not normally instantiated directly. In most
35/// cases, you'll create one as a side effect of encrypting a message
36/// using the [streaming serializer], or parsing an encrypted message
37/// using the [`PacketParser`].
38///
39/// [SEIP]: crate::packet::SEIP
40/// [Section 5.3 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.3
41/// [streaming serializer]: crate::serialize::stream
42/// [`PacketParser`]: crate::parse::PacketParser
43#[non_exhaustive]
44#[derive(PartialEq, Eq, Hash, Clone, Debug)]
45pub enum SKESK {
46 /// SKESK packet version 4.
47 V4(self::SKESK4),
48
49 /// SKESK packet version 6.
50 V6(self::SKESK6),
51}
52assert_send_and_sync!(SKESK);
53
54impl SKESK {
55 /// Gets the version.
56 pub fn version(&self) -> u8 {
57 match self {
58 SKESK::V4(_) => 4,
59 SKESK::V6(_) => 6,
60 }
61 }
62
63 /// Derives the key inside this SKESK from `password`.
64 ///
65 /// Returns a tuple of the symmetric cipher to use with the key
66 /// and the key itself, if this information is parsed from the
67 /// SKESK4 pakcket. The symmetric cipher will be omitted for
68 /// SKESK6 packets, which don't carry that information.
69 pub fn decrypt(&self, password: &Password)
70 -> Result<(Option<SymmetricAlgorithm>, SessionKey)>
71 {
72 match self {
73 SKESK::V4(s) => s.decrypt(password)
74 .map(|(algo, sk)| (Some(algo), sk)),
75 SKESK::V6(ref s) =>
76 Ok((None, s.decrypt(password)?)),
77 }
78 }
79}
80
81impl From<SKESK> for Packet {
82 fn from(p: SKESK) -> Self {
83 Packet::SKESK(p)
84 }
85}
86
87#[cfg(test)]
88impl Arbitrary for SKESK {
89 fn arbitrary(g: &mut Gen) -> Self {
90 if bool::arbitrary(g) {
91 SKESK::V4(SKESK4::arbitrary(g))
92 } else {
93 SKESK::V6(SKESK6::arbitrary(g))
94 }
95 }
96}