oxigdal_security/encryption/
envelope.rs1use crate::encryption::{AtRestEncryptor, EncryptedData, EncryptionAlgorithm};
4use crate::error::{Result, SecurityError};
5use serde::{Deserialize, Serialize};
6
7pub trait KekProvider: Send + Sync {
9 fn encrypt_dek(&self, dek: &[u8]) -> Result<Vec<u8>>;
11
12 fn decrypt_dek(&self, encrypted_dek: &[u8]) -> Result<Vec<u8>>;
14
15 fn kek_id(&self) -> &str;
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct EnvelopeEncryptedData {
22 pub encrypted_dek: Vec<u8>,
24 pub kek_id: String,
26 pub encrypted_payload: EncryptedData,
28 pub dek_algorithm: EncryptionAlgorithm,
30}
31
32impl EnvelopeEncryptedData {
33 pub fn to_json_bytes(&self) -> Result<Vec<u8>> {
35 serde_json::to_vec(self).map_err(SecurityError::from)
36 }
37
38 pub fn from_json_bytes(bytes: &[u8]) -> Result<Self> {
40 serde_json::from_slice(bytes).map_err(SecurityError::from)
41 }
42}
43
44pub struct EnvelopeEncryptor {
46 kek_provider: Box<dyn KekProvider>,
47 dek_algorithm: EncryptionAlgorithm,
48}
49
50impl EnvelopeEncryptor {
51 pub fn new(kek_provider: Box<dyn KekProvider>, dek_algorithm: EncryptionAlgorithm) -> Self {
53 Self {
54 kek_provider,
55 dek_algorithm,
56 }
57 }
58
59 pub fn encrypt(&self, plaintext: &[u8], aad: Option<&[u8]>) -> Result<EnvelopeEncryptedData> {
61 let dek = AtRestEncryptor::generate_key(self.dek_algorithm);
63
64 let dek_id = uuid::Uuid::new_v4().to_string();
66 let encryptor = AtRestEncryptor::new(self.dek_algorithm, dek.clone(), dek_id)?;
67 let encrypted_payload = encryptor.encrypt(plaintext, aad)?;
68
69 let encrypted_dek = self.kek_provider.encrypt_dek(&dek)?;
71
72 Ok(EnvelopeEncryptedData {
73 encrypted_dek,
74 kek_id: self.kek_provider.kek_id().to_string(),
75 encrypted_payload,
76 dek_algorithm: self.dek_algorithm,
77 })
78 }
79
80 pub fn decrypt(&self, envelope: &EnvelopeEncryptedData) -> Result<Vec<u8>> {
82 if envelope.kek_id != self.kek_provider.kek_id() {
84 return Err(SecurityError::decryption(format!(
85 "KEK ID mismatch: expected {}, got {}",
86 self.kek_provider.kek_id(),
87 envelope.kek_id
88 )));
89 }
90
91 let dek = self.kek_provider.decrypt_dek(&envelope.encrypted_dek)?;
93
94 let dek_id = envelope.encrypted_payload.metadata.key_id.clone();
96 let encryptor = AtRestEncryptor::new(envelope.dek_algorithm, dek, dek_id)?;
97 encryptor.decrypt(&envelope.encrypted_payload)
98 }
99
100 pub fn kek_id(&self) -> &str {
102 self.kek_provider.kek_id()
103 }
104
105 pub fn dek_algorithm(&self) -> EncryptionAlgorithm {
107 self.dek_algorithm
108 }
109}
110
111pub struct InMemoryKekProvider {
113 kek_id: String,
114 encryptor: AtRestEncryptor,
115}
116
117impl InMemoryKekProvider {
118 pub fn new(kek_id: String) -> Result<Self> {
120 let kek = AtRestEncryptor::generate_key(EncryptionAlgorithm::Aes256Gcm);
121 let encryptor = AtRestEncryptor::new(EncryptionAlgorithm::Aes256Gcm, kek, kek_id.clone())?;
122
123 Ok(Self { kek_id, encryptor })
124 }
125
126 pub fn with_kek(kek_id: String, kek: Vec<u8>) -> Result<Self> {
128 let encryptor = AtRestEncryptor::new(EncryptionAlgorithm::Aes256Gcm, kek, kek_id.clone())?;
129
130 Ok(Self { kek_id, encryptor })
131 }
132}
133
134impl KekProvider for InMemoryKekProvider {
135 fn encrypt_dek(&self, dek: &[u8]) -> Result<Vec<u8>> {
136 let encrypted = self.encryptor.encrypt(dek, None)?;
137 encrypted.to_json_bytes()
138 }
139
140 fn decrypt_dek(&self, encrypted_dek: &[u8]) -> Result<Vec<u8>> {
141 let encrypted = EncryptedData::from_json_bytes(encrypted_dek)?;
142 self.encryptor.decrypt(&encrypted)
143 }
144
145 fn kek_id(&self) -> &str {
146 &self.kek_id
147 }
148}
149
150pub struct MultiRegionKekProvider {
152 kek_id: String,
153 primary: Box<dyn KekProvider>,
154 secondary: Option<Box<dyn KekProvider>>,
155}
156
157impl MultiRegionKekProvider {
158 pub fn new(
160 kek_id: String,
161 primary: Box<dyn KekProvider>,
162 secondary: Option<Box<dyn KekProvider>>,
163 ) -> Self {
164 Self {
165 kek_id,
166 primary,
167 secondary,
168 }
169 }
170
171 pub fn encrypt_with_both(&self, dek: &[u8]) -> Result<(Vec<u8>, Option<Vec<u8>>)> {
173 let primary_encrypted = self.primary.encrypt_dek(dek)?;
174 let secondary_encrypted = if let Some(ref secondary) = self.secondary {
175 Some(secondary.encrypt_dek(dek)?)
176 } else {
177 None
178 };
179
180 Ok((primary_encrypted, secondary_encrypted))
181 }
182}
183
184impl KekProvider for MultiRegionKekProvider {
185 fn encrypt_dek(&self, dek: &[u8]) -> Result<Vec<u8>> {
186 self.primary.encrypt_dek(dek)
187 }
188
189 fn decrypt_dek(&self, encrypted_dek: &[u8]) -> Result<Vec<u8>> {
190 match self.primary.decrypt_dek(encrypted_dek) {
192 Ok(dek) => Ok(dek),
193 Err(e) => {
194 if let Some(ref secondary) = self.secondary {
196 secondary.decrypt_dek(encrypted_dek)
197 } else {
198 Err(e)
199 }
200 }
201 }
202 }
203
204 fn kek_id(&self) -> &str {
205 &self.kek_id
206 }
207}
208
209#[cfg(test)]
210mod tests {
211 use super::*;
212
213 #[test]
214 fn test_in_memory_kek_provider() {
215 let provider =
216 InMemoryKekProvider::new("test-kek".to_string()).expect("Failed to create provider");
217
218 let dek = AtRestEncryptor::generate_key(EncryptionAlgorithm::Aes256Gcm);
219 let encrypted_dek = provider.encrypt_dek(&dek).expect("Encryption failed");
220
221 assert_ne!(encrypted_dek, dek);
222
223 let decrypted_dek = provider
224 .decrypt_dek(&encrypted_dek)
225 .expect("Decryption failed");
226 assert_eq!(decrypted_dek, dek);
227 }
228
229 #[test]
230 fn test_envelope_encryption() {
231 let kek_provider =
232 InMemoryKekProvider::new("test-kek".to_string()).expect("Failed to create provider");
233 let encryptor =
234 EnvelopeEncryptor::new(Box::new(kek_provider), EncryptionAlgorithm::Aes256Gcm);
235
236 let plaintext = b"sensitive data";
237 let envelope = encryptor
238 .encrypt(plaintext, None)
239 .expect("Encryption failed");
240
241 assert_ne!(envelope.encrypted_payload.ciphertext, plaintext);
242 assert!(!envelope.encrypted_dek.is_empty());
243
244 let decrypted = encryptor.decrypt(&envelope).expect("Decryption failed");
245 assert_eq!(decrypted, plaintext);
246 }
247
248 #[test]
249 fn test_envelope_with_aad() {
250 let kek_provider =
251 InMemoryKekProvider::new("test-kek".to_string()).expect("Failed to create provider");
252 let encryptor =
253 EnvelopeEncryptor::new(Box::new(kek_provider), EncryptionAlgorithm::Aes256Gcm);
254
255 let plaintext = b"sensitive data";
256 let aad = b"additional data";
257 let envelope = encryptor
258 .encrypt(plaintext, Some(aad))
259 .expect("Encryption failed");
260
261 let decrypted = encryptor.decrypt(&envelope).expect("Decryption failed");
262 assert_eq!(decrypted, plaintext);
263 }
264
265 #[test]
266 fn test_multi_region_kek_provider() {
267 let primary =
268 InMemoryKekProvider::new("primary-kek".to_string()).expect("Failed to create primary");
269 let secondary = InMemoryKekProvider::new("secondary-kek".to_string())
270 .expect("Failed to create secondary");
271
272 let multi = MultiRegionKekProvider::new(
273 "multi-kek".to_string(),
274 Box::new(primary),
275 Some(Box::new(secondary)),
276 );
277
278 let dek = AtRestEncryptor::generate_key(EncryptionAlgorithm::Aes256Gcm);
279 let encrypted_dek = multi.encrypt_dek(&dek).expect("Encryption failed");
280
281 let decrypted_dek = multi
282 .decrypt_dek(&encrypted_dek)
283 .expect("Decryption failed");
284 assert_eq!(decrypted_dek, dek);
285 }
286
287 #[test]
288 fn test_envelope_serialization() {
289 let kek_provider =
290 InMemoryKekProvider::new("test-kek".to_string()).expect("Failed to create provider");
291 let encryptor =
292 EnvelopeEncryptor::new(Box::new(kek_provider), EncryptionAlgorithm::Aes256Gcm);
293
294 let plaintext = b"sensitive data";
295 let envelope = encryptor
296 .encrypt(plaintext, None)
297 .expect("Encryption failed");
298
299 let json = envelope.to_json_bytes().expect("Serialization failed");
300 let deserialized =
301 EnvelopeEncryptedData::from_json_bytes(&json).expect("Deserialization failed");
302
303 let decrypted = encryptor.decrypt(&deserialized).expect("Decryption failed");
304 assert_eq!(decrypted, plaintext);
305 }
306}