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