1use std::fmt::Debug;
2
3use openmls_traits::{
4 crypto::OpenMlsCrypto,
5 random::OpenMlsRand,
6 storage::{StorageProvider as StorageProviderTrait, CURRENT_VERSION},
7 types::{Ciphersuite, HpkeCiphertext, HpkeKeyPair},
8};
9use serde::{Deserialize, Serialize};
10use tls_codec::{TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize, VLBytes};
11
12use crate::{
13 ciphersuite::{hpke, HpkePrivateKey, HpkePublicKey, Secret},
14 error::LibraryError,
15 storage::{OpenMlsProvider, StorageProvider},
16};
17
18#[derive(
21 Debug,
22 Clone,
23 Serialize,
24 Deserialize,
25 TlsSerialize,
26 TlsDeserialize,
27 TlsDeserializeBytes,
28 TlsSize,
29 PartialEq,
30 Eq,
31 Hash,
32)]
33pub struct EncryptionKey {
34 key: HpkePublicKey,
35}
36
37impl EncryptionKey {
38 pub(crate) fn key(&self) -> &HpkePublicKey {
40 &self.key
41 }
42
43 pub(crate) fn as_slice(&self) -> &[u8] {
45 self.key.as_slice()
46 }
47
48 pub(crate) fn encrypt(
50 &self,
51 crypto: &impl OpenMlsCrypto,
52 ciphersuite: Ciphersuite,
53 context: &[u8],
54 plaintext: &[u8],
55 ) -> Result<HpkeCiphertext, LibraryError> {
56 hpke::encrypt_with_label(
57 self.as_slice(),
58 "UpdatePathNode",
59 context,
60 plaintext,
61 ciphersuite,
62 crypto,
63 )
64 .map_err(|_| LibraryError::custom("Encryption failed. A serialization issue really"))
65 }
66}
67
68#[cfg(feature = "targeted-messages-draft")]
69impl EncryptionKey {
70 pub(crate) fn encrypt_with_label_psk_resolved_aad<F>(
71 &self,
72 params: hpke::PskEncryptParams,
73 plaintext: &[u8],
74 crypto: &impl OpenMlsCrypto,
75 aad_builder: F,
76 ) -> Result<HpkeCiphertext, LibraryError>
77 where
78 F: FnOnce(&[u8]) -> Result<Vec<u8>, LibraryError>,
79 {
80 hpke::encrypt_with_label_psk_resolved_aad(
81 self.as_slice(),
82 params,
83 plaintext,
84 crypto,
85 aad_builder,
86 )
87 }
88}
89
90impl From<Vec<u8>> for EncryptionKey {
91 fn from(key: Vec<u8>) -> Self {
92 Self { key: key.into() }
93 }
94}
95
96#[derive(
97 Clone, Serialize, Deserialize, TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize,
98)]
99#[cfg_attr(any(test, feature = "test-utils"), derive(PartialEq, Eq))]
100pub struct EncryptionPrivateKey {
101 key: HpkePrivateKey,
102}
103
104impl Debug for EncryptionPrivateKey {
105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106 let mut ds = f.debug_struct("EncryptionPrivateKey");
107
108 #[cfg(feature = "crypto-debug")]
109 ds.field("key", &self.key);
110 #[cfg(not(feature = "crypto-debug"))]
111 ds.field("key", &"***");
112
113 ds.finish()
114 }
115}
116
117impl From<Vec<u8>> for EncryptionPrivateKey {
118 fn from(key: Vec<u8>) -> Self {
119 Self { key: key.into() }
120 }
121}
122
123impl From<HpkePrivateKey> for EncryptionPrivateKey {
124 fn from(key: HpkePrivateKey) -> Self {
125 Self { key }
126 }
127}
128
129impl EncryptionPrivateKey {
130 pub(crate) fn decrypt(
136 &self,
137 crypto: &impl OpenMlsCrypto,
138 ciphersuite: Ciphersuite,
139 ciphertext: &HpkeCiphertext,
140 group_context: &[u8],
141 ) -> Result<Secret, hpke::Error> {
142 hpke::decrypt_with_label(
144 &self.key,
145 "UpdatePathNode",
146 group_context,
147 ciphertext,
148 ciphersuite,
149 crypto,
150 )
151 .map(|secret_bytes| Secret::from_slice(&secret_bytes))
152 }
153
154 #[cfg(feature = "targeted-messages-draft")]
155 pub(crate) fn decrypt_with_label_psk_aad(
156 &self,
157 params: hpke::PskEncryptParams,
158 aad: &[u8],
159 ciphertext: &HpkeCiphertext,
160 crypto: &impl OpenMlsCrypto,
161 ) -> Result<Vec<u8>, hpke::Error> {
162 hpke::decrypt_with_label_psk_aad(&self.key, params, aad, ciphertext, crypto)
163 }
164}
165
166#[cfg(any(test, feature = "test-utils"))]
167impl EncryptionPrivateKey {
168 pub(crate) fn key(&self) -> &HpkePrivateKey {
169 &self.key
170 }
171}
172
173impl From<HpkePublicKey> for EncryptionKey {
174 fn from(key: HpkePublicKey) -> Self {
175 Self { key }
176 }
177}
178
179#[derive(
180 Debug, Clone, Serialize, Deserialize, TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize,
181)]
182#[cfg_attr(any(test, feature = "test-utils"), derive(PartialEq, Eq))]
183pub(crate) struct EncryptionKeyPair {
184 public_key: EncryptionKey,
185 private_key: EncryptionPrivateKey,
186}
187
188impl EncryptionKeyPair {
189 pub(crate) fn write<Storage: StorageProvider>(
195 &self,
196 store: &Storage,
197 ) -> Result<(), Storage::Error> {
198 store.write_encryption_key_pair(self.public_key(), self)
199 }
200
201 pub(crate) fn read(
211 provider: &impl OpenMlsProvider,
212 encryption_key: &EncryptionKey,
213 ) -> Option<EncryptionKeyPair> {
214 provider
215 .storage()
216 .encryption_key_pair(encryption_key)
217 .ok()
218 .flatten()
219 }
220
221 pub(crate) fn delete<Storage: StorageProviderTrait<CURRENT_VERSION>>(
227 &self,
228 store: &Storage,
229 ) -> Result<(), Storage::Error> {
230 store.delete_encryption_key_pair(self.public_key())
231 }
232
233 pub(crate) fn public_key(&self) -> &EncryptionKey {
234 &self.public_key
235 }
236
237 pub(crate) fn private_key(&self) -> &EncryptionPrivateKey {
238 &self.private_key
239 }
240
241 pub(crate) fn random(
242 rand: &impl OpenMlsRand,
243 crypto: &impl OpenMlsCrypto,
244 ciphersuite: Ciphersuite,
245 ) -> Result<Self, LibraryError> {
246 let ikm =
247 Secret::random(ciphersuite, rand).map_err(LibraryError::unexpected_crypto_error)?;
248 Ok(crypto
249 .derive_hpke_keypair(ciphersuite.hpke_config(), ikm.as_slice())
250 .map_err(LibraryError::unexpected_crypto_error)?
251 .into())
252 }
253}
254
255#[cfg(feature = "test-utils")]
256pub mod test_utils {
257 use super::*;
258
259 pub fn read_keys_from_key_store(
260 provider: &impl OpenMlsProvider,
261 encryption_key: &EncryptionKey,
262 ) -> HpkeKeyPair {
263 let keys = EncryptionKeyPair::read(provider, encryption_key).unwrap();
264
265 HpkeKeyPair {
266 private: keys.private_key.key,
267 public: keys.public_key.key.as_slice().to_vec(),
268 }
269 }
270
271 pub fn write_keys_from_key_store(provider: &impl OpenMlsProvider, encryption_key: HpkeKeyPair) {
272 let keypair = EncryptionKeyPair::from(encryption_key);
273
274 keypair.write(provider.storage()).unwrap();
275 }
276}
277
278#[cfg(test)]
279impl EncryptionKeyPair {
280 pub(crate) fn from_raw(public_key: Vec<u8>, private_key: Vec<u8>) -> Self {
282 Self {
283 public_key: EncryptionKey {
284 key: public_key.into(),
285 },
286 private_key: EncryptionPrivateKey {
287 key: private_key.into(),
288 },
289 }
290 }
291}
292
293impl From<(HpkePublicKey, HpkePrivateKey)> for EncryptionKeyPair {
294 fn from((public_key, private_key): (HpkePublicKey, HpkePrivateKey)) -> Self {
295 Self {
296 public_key: public_key.into(),
297 private_key: private_key.into(),
298 }
299 }
300}
301
302impl From<HpkeKeyPair> for EncryptionKeyPair {
303 fn from(hpke_keypair: HpkeKeyPair) -> Self {
304 let public_bytes: VLBytes = hpke_keypair.public.into();
305 let private_bytes = hpke_keypair.private;
306 Self {
307 public_key: public_bytes.into(),
308 private_key: private_bytes.into(),
309 }
310 }
311}
312
313impl From<(EncryptionKey, EncryptionPrivateKey)> for EncryptionKeyPair {
314 fn from((public_key, private_key): (EncryptionKey, EncryptionPrivateKey)) -> Self {
315 Self {
316 public_key,
317 private_key,
318 }
319 }
320}