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}