sequoia_openpgp/packet/pkesk/
v6.rs1#[cfg(test)]
10use quickcheck::{Arbitrary, Gen};
11
12use crate::packet::key;
13use crate::packet::Key;
14use crate::Fingerprint;
15use crate::crypto::Decryptor;
16use crate::crypto::mpi::Ciphertext;
17use crate::Packet;
18use crate::PublicKeyAlgorithm;
19use crate::Result;
20use crate::SymmetricAlgorithm;
21use crate::crypto::SessionKey;
22use crate::packet;
23
24#[derive(Clone, Debug, PartialEq, Eq, Hash)]
32pub struct PKESK6 {
33 pub(crate) common: packet::Common,
35
36 recipient: Option<Fingerprint>,
41
42 pk_algo: PublicKeyAlgorithm,
44
45 esk: Ciphertext,
47}
48
49assert_send_and_sync!(PKESK6);
50
51impl PKESK6 {
52 pub fn new(recipient: Option<Fingerprint>, pk_algo: PublicKeyAlgorithm,
54 encrypted_session_key: Ciphertext)
55 -> Result<PKESK6>
56 {
57 Ok(PKESK6 {
58 common: Default::default(),
59 recipient,
60 pk_algo,
61 esk: encrypted_session_key,
62 })
63 }
64
65 pub fn for_recipient<P, R>(session_key: &SessionKey,
70 recipient: &Key<P, R>)
71 -> Result<PKESK6>
72 where
73 P: key::KeyParts,
74 R: key::KeyRole,
75 {
76 #[allow(deprecated)]
78 if recipient.pk_algo() == PublicKeyAlgorithm::ElGamalEncrypt
79 || recipient.pk_algo() == PublicKeyAlgorithm::ElGamalEncryptSign
80 {
81 return Err(crate::Error::InvalidOperation(
82 "MUST NOT encrypt with version 6 ElGamal keys".into())
83 .into());
84 }
85
86 Ok(PKESK6 {
87 common: Default::default(),
88 recipient: Some(recipient.fingerprint()),
89 pk_algo: recipient.pk_algo(),
90 esk: packet::PKESK::encrypt_common(
91 None, session_key,
92 recipient.parts_as_unspecified().role_as_unspecified())?,
93 })
94 }
95
96 pub fn recipient(&self) -> Option<&Fingerprint> {
98 self.recipient.as_ref()
99 }
100
101 pub fn set_recipient(&mut self, recipient: Option<Fingerprint>)
103 -> Option<Fingerprint> {
104 std::mem::replace(&mut self.recipient, recipient)
105 }
106
107 pub fn pk_algo(&self) -> PublicKeyAlgorithm {
109 self.pk_algo
110 }
111
112 pub fn set_pk_algo(&mut self, algo: PublicKeyAlgorithm)
114 -> PublicKeyAlgorithm {
115 std::mem::replace(&mut self.pk_algo, algo)
116 }
117
118 pub fn esk(&self) -> &Ciphertext {
120 &self.esk
121 }
122
123 pub fn set_esk(&mut self, esk: Ciphertext) -> Ciphertext {
125 std::mem::replace(&mut self.esk, esk)
126 }
127
128 pub fn decrypt(&self, decryptor: &mut dyn Decryptor,
145 sym_algo_hint: Option<SymmetricAlgorithm>)
146 -> Option<SessionKey>
147 {
148 self.decrypt_insecure(decryptor, sym_algo_hint).ok()
149 }
150
151 fn decrypt_insecure(&self, decryptor: &mut dyn Decryptor,
152 sym_algo_hint: Option<SymmetricAlgorithm>)
153 -> Result<SessionKey>
154 {
155 packet::PKESK::decrypt_common(&self.esk, decryptor, sym_algo_hint, false)
156 .map(|(_sym_algo, key)| key)
157 }
158}
159
160impl From<PKESK6> for packet::PKESK {
161 fn from(p: PKESK6) -> Self {
162 packet::PKESK::V6(p)
163 }
164}
165
166impl From<PKESK6> for Packet {
167 fn from(p: PKESK6) -> Self {
168 Packet::PKESK(p.into())
169 }
170}
171
172#[cfg(test)]
173impl Arbitrary for PKESK6 {
174 fn arbitrary(g: &mut Gen) -> Self {
175 let (ciphertext, pk_algo) = loop {
176 let ciphertext = Ciphertext::arbitrary(g);
177 if let Some(pk_algo) = ciphertext.pk_algo() {
178 break (ciphertext, pk_algo);
179 }
180 };
181
182 PKESK6::new(bool::arbitrary(g).then(|| Fingerprint::arbitrary_v6(g)),
183 pk_algo, ciphertext).unwrap()
184 }
185}
186
187#[cfg(test)]
188mod tests {
189 use super::*;
190 use crate::parse::Parse;
191 use crate::serialize::MarshalInto;
192
193 quickcheck! {
194 fn roundtrip(p: PKESK6) -> bool {
195 let q = PKESK6::from_bytes(&p.to_vec().unwrap()).unwrap();
196 assert_eq!(p, q);
197 true
198 }
199 }
200}