1pub mod errors;
2pub mod traits;
3
4pub use errors::EnclaveError;
5pub use traits::{Decryptable, Encryptable};
6
7pub use secured_cipher::{
8 algorithm::chacha20::CHACHA20_NONCE_SIZE, random_bytes, Cipher, Key, KeyDerivationStrategy,
9 SignedEnvelope,
10};
11
12const KEY_SIZE: usize = 32;
13const NONCE_SIZE: usize = CHACHA20_NONCE_SIZE;
14
15#[derive(Debug, Clone)]
23pub struct Enclave<T> {
24 pub metadata: T,
26
27 pub encrypted_bytes: Box<[u8]>,
29
30 pub nonce: [u8; NONCE_SIZE],
32}
33
34impl<T> Enclave<T>
35where
36 T: TryFrom<Vec<u8>> + Into<Vec<u8>> + Clone,
37{
38 pub fn from_plain_bytes(
48 metadata: T,
49 key: [u8; KEY_SIZE],
50 plain_bytes: Vec<u8>,
51 ) -> Result<Self, String> {
52 let nonce = random_bytes::<NONCE_SIZE>();
53 let mut cipher = Cipher::default();
54 cipher.init(&key, &nonce);
55
56 let encrypted_bytes = cipher.encrypt(&plain_bytes);
57 let envelope: Vec<u8> = cipher
58 .sign(&metadata.clone().into(), &encrypted_bytes)
59 .into();
60
61 Ok(Enclave {
62 metadata,
63 encrypted_bytes: envelope.into_boxed_slice(),
64 nonce,
65 })
66 }
67
68 pub fn decrypt(&self, key: [u8; KEY_SIZE]) -> Result<Vec<u8>, EnclaveError> {
76 let envelope = SignedEnvelope::from(self.encrypted_bytes.to_vec());
77
78 Ok(
79 Cipher::default()
80 .init(&key, &self.nonce)
81 .decrypt_and_verify(&envelope)?,
82 )
83 }
84
85 pub fn recover_key(
93 encrypted_bytes: &[u8],
94 password: &[u8],
95 ) -> Result<Key<KEY_SIZE, 16>, EnclaveError> {
96 let strategy = KeyDerivationStrategy::try_from(
97 encrypted_bytes[encrypted_bytes.len() - 9..encrypted_bytes.len()].to_vec(),
98 )?;
99 let salt: [u8; 16] = encrypted_bytes[encrypted_bytes.len() - 25..encrypted_bytes.len() - 9]
100 .try_into()
101 .unwrap();
102 let key = Key::<KEY_SIZE, 16>::with_salt(password, salt, strategy);
103
104 Ok(key)
105 }
106}
107
108impl<T> From<Enclave<T>> for Vec<u8>
109where
110 T: TryFrom<Vec<u8>> + Into<Vec<u8>>,
111{
112 fn from(enclave: Enclave<T>) -> Vec<u8> {
120 let mut bytes: Vec<u8> = vec![];
121 let metadata_bytes = enclave.metadata.into();
122
123 bytes.append(&mut vec![u8::try_from(metadata_bytes.len()).unwrap()]);
124 bytes.append(&mut metadata_bytes.into());
125 bytes.append(&mut enclave.encrypted_bytes.into());
126 bytes.append(&mut enclave.nonce.to_vec());
127
128 bytes
129 }
130}
131
132impl<T> TryFrom<Vec<u8>> for Enclave<T>
133where
134 T: TryFrom<Vec<u8>> + Into<Vec<u8>>,
135{
136 type Error = EnclaveError;
137
138 fn try_from(bytes: Vec<u8>) -> Result<Self, EnclaveError> {
146 if bytes.len() == 0 {
147 return Err(EnclaveError::Deserialization("No bytes found".to_string()));
148 }
149 let metadata_len = bytes[0];
150 if usize::from(metadata_len) > bytes.len() {
151 return Err(EnclaveError::Deserialization(
152 "unexpected metadata length".to_string(),
153 ));
154 }
155 let metadata = T::try_from(bytes[1..metadata_len as usize + 1].to_vec()).or(Err(
156 EnclaveError::Deserialization("error deserializing metadata".to_string()),
157 ))?;
158 let encrypted_bytes = bytes[metadata_len as usize + 1..bytes.len() - NONCE_SIZE].to_vec();
159 let nonce = bytes[bytes.len() - NONCE_SIZE..bytes.len()].to_vec();
160
161 Ok(Enclave {
162 metadata,
163 encrypted_bytes: encrypted_bytes.into_boxed_slice(),
164 nonce: nonce.try_into().or(Err(EnclaveError::Deserialization(
165 "unexpected bytes length".to_string(),
166 )))?,
167 })
168 }
169}
170
171impl<T> PartialEq for Enclave<T>
172where
173 T: PartialEq + TryFrom<Vec<u8>> + Into<Vec<u8>>,
174{
175 fn eq(&self, other: &Self) -> bool {
183 self.metadata == other.metadata
184 && self.encrypted_bytes == other.encrypted_bytes
185 && self.nonce == other.nonce
186 }
187}
188
189impl Encryptable<KEY_SIZE> for Vec<u8> {
190 fn encrypt(&self, password: String, strategy: KeyDerivationStrategy) -> Vec<u8> {
199 let key: Key<32, 16> = Key::new(password.as_bytes(), strategy.clone());
200 let enclave = Enclave::from_plain_bytes(vec![], key.pubk, self.clone()).unwrap();
201
202 [enclave.into(), key.salt.to_vec(), strategy.into()].concat()
203 }
204
205 fn encrypt_with_key(&self, key: &Key<32, 16>) -> Vec<u8> {
213 let enclave = Enclave::from_plain_bytes(vec![], key.pubk, self.clone()).unwrap();
214 [
215 enclave.into(),
216 key.salt.to_vec(),
217 key.strategy.clone().into(),
218 ]
219 .concat()
220 }
221
222 fn encrypt_with_raw_key(&self, key: [u8; KEY_SIZE]) -> Vec<u8> {
230 let enclave = Enclave::from_plain_bytes(vec![], key, self.clone()).unwrap();
231 enclave.into()
232 }
233
234 fn encrypt_with_metadata<M>(&self, key: [u8; KEY_SIZE], metadata: M) -> Vec<u8>
243 where
244 M: From<Vec<u8>> + Into<Vec<u8>> + Clone,
245 {
246 let enclave = Enclave::from_plain_bytes(metadata, key, self.clone()).unwrap();
247 enclave.into()
248 }
249}
250
251impl Decryptable<KEY_SIZE> for Vec<u8> {
252 fn decrypt(&self, password: String) -> Result<Vec<u8>, EnclaveError> {
260 let strategy = KeyDerivationStrategy::try_from(self[self.len() - 9..self.len()].to_vec())?;
261 let salt: [u8; 16] = self[self.len() - 25..self.len() - 9].try_into().unwrap();
262 let key = Key::<KEY_SIZE, 16>::with_salt(password.as_bytes(), salt, strategy);
263
264 let enclave = Enclave::<Vec<u8>>::try_from(self[..self.len() - 25].to_vec())?;
265
266 enclave.decrypt(key.pubk)
267 }
268
269 fn decrypt_with_key(&self, key: [u8; KEY_SIZE]) -> Result<Vec<u8>, EnclaveError> {
277 let enclave = Enclave::<Vec<u8>>::try_from(self.clone())?;
278 enclave.decrypt(key)
279 }
280
281 fn decrypt_with_metadata<M>(&self, key: [u8; KEY_SIZE]) -> Result<(Vec<u8>, M), EnclaveError>
289 where
290 M: TryFrom<Vec<u8>> + Into<Vec<u8>> + Clone,
291 {
292 let enclave = Enclave::<M>::try_from(self.clone())?;
293 let decrypted_bytes = enclave.decrypt(key)?;
294 Ok((decrypted_bytes, enclave.metadata))
295 }
296}
297
298impl Decryptable<KEY_SIZE> for &[u8] {
299 fn decrypt(&self, password: String) -> Result<Vec<u8>, EnclaveError> {
307 self.to_vec().decrypt(password)
308 }
309
310 fn decrypt_with_key(&self, key: [u8; KEY_SIZE]) -> Result<Vec<u8>, EnclaveError> {
318 self.to_vec().decrypt_with_key(key)
319 }
320
321 fn decrypt_with_metadata<M>(&self, key: [u8; KEY_SIZE]) -> Result<(Vec<u8>, M), EnclaveError>
329 where
330 M: TryFrom<Vec<u8>> + Into<Vec<u8>> + Clone,
331 {
332 self.to_vec().decrypt_with_metadata(key)
333 }
334}
335
336impl Encryptable<KEY_SIZE> for &[u8] {
337 fn encrypt(&self, password: String, strategy: KeyDerivationStrategy) -> Vec<u8> {
346 self.to_vec().encrypt(password, strategy)
347 }
348
349 fn encrypt_with_key(&self, key: &Key<32, 16>) -> Vec<u8> {
357 self.to_vec().encrypt_with_key(key)
358 }
359
360 fn encrypt_with_raw_key(&self, key: [u8; KEY_SIZE]) -> Vec<u8> {
368 self.to_vec().encrypt_with_raw_key(key)
369 }
370
371 fn encrypt_with_metadata<M>(&self, key: [u8; KEY_SIZE], metadata: M) -> Vec<u8>
380 where
381 M: From<Vec<u8>> + Into<Vec<u8>> + Clone,
382 {
383 self.to_vec().encrypt_with_metadata(key, metadata)
384 }
385}
386
387impl Encryptable<KEY_SIZE> for String {
388 fn encrypt(&self, password: String, strategy: KeyDerivationStrategy) -> Vec<u8> {
397 self.as_bytes().to_vec().encrypt(password, strategy)
398 }
399
400 fn encrypt_with_key(&self, key: &Key<32, 16>) -> Vec<u8> {
408 self.as_bytes().to_vec().encrypt_with_key(key)
409 }
410
411 fn encrypt_with_raw_key(&self, key: [u8; KEY_SIZE]) -> Vec<u8> {
419 self.as_bytes().to_vec().encrypt_with_raw_key(key)
420 }
421
422 fn encrypt_with_metadata<M>(&self, key: [u8; KEY_SIZE], metadata: M) -> Vec<u8>
431 where
432 M: From<Vec<u8>> + Into<Vec<u8>> + Clone,
433 {
434 self
435 .as_bytes()
436 .to_vec()
437 .encrypt_with_metadata(key, metadata)
438 }
439}
440
441impl Encryptable<KEY_SIZE> for &str {
442 fn encrypt(&self, password: String, strategy: KeyDerivationStrategy) -> Vec<u8> {
450 self.as_bytes().to_vec().encrypt(password, strategy)
451 }
452
453 fn encrypt_with_key(&self, key: &Key<32, 16>) -> Vec<u8> {
461 self.as_bytes().to_vec().encrypt_with_key(key)
462 }
463
464 fn encrypt_with_raw_key(&self, key: [u8; KEY_SIZE]) -> Vec<u8> {
472 self.as_bytes().to_vec().encrypt_with_raw_key(key)
473 }
474
475 fn encrypt_with_metadata<M>(&self, key: [u8; KEY_SIZE], metadata: M) -> Vec<u8>
484 where
485 M: From<Vec<u8>> + Into<Vec<u8>> + Clone,
486 {
487 self
488 .as_bytes()
489 .to_vec()
490 .encrypt_with_metadata(key, metadata)
491 }
492}
493
494#[cfg(test)]
495mod tests {
496 use super::*;
497
498 mod from_plain_bytes {
499 use super::*;
500
501 #[test]
502 fn it_should_create_enclave() {
503 let key = [0u8; KEY_SIZE];
504 let bytes = [0u8, 1u8, 2u8, 3u8, 4u8].to_vec();
505
506 let safe = Enclave::from_plain_bytes(b"metadata".to_owned(), key, bytes);
507
508 assert!(safe.is_ok());
509 assert_eq!(safe.unwrap().metadata, b"metadata".to_owned());
510 }
511 }
512
513 mod decrypt {
514 use super::*;
515
516 #[test]
517 fn it_should_decrypt_enclave() {
518 let key = [0u8; KEY_SIZE];
519 let bytes = [0u8, 1u8, 2u8, 3u8, 4u8].to_vec();
520 let safe = Enclave::from_plain_bytes(b"metadata".to_vec(), key, bytes.clone()).unwrap();
521
522 let decrypted_bytes = safe.decrypt(key);
523
524 assert!(decrypted_bytes.is_ok());
525 assert_eq!(decrypted_bytes.unwrap(), bytes);
526 }
527
528 #[test]
529 fn it_should_fail_with_wrong_key() {
530 let key = [0u8; KEY_SIZE];
531 let bytes = [0u8, 1u8, 2u8, 3u8, 4u8].to_vec();
532 let safe = Enclave::from_plain_bytes(b"metadata".to_vec(), key, bytes.clone()).unwrap();
533 let wrong_key = [1u8; KEY_SIZE];
534
535 let decrypted_bytes = safe.decrypt(wrong_key);
536
537 assert!(!decrypted_bytes.is_ok());
538 }
539
540 #[test]
541 fn it_should_serialize_and_deserialize_to_bytes() {
542 let key = [0u8; KEY_SIZE];
543 let bytes = [0u8, 1u8, 2u8, 3u8, 4u8].to_vec();
544 let enclave = Enclave::from_plain_bytes([0_u8, 1_u8], key, bytes.clone()).unwrap();
545
546 let serialized: Vec<u8> = enclave.clone().into();
547 let deserialized = Enclave::try_from(serialized).unwrap();
548
549 assert_eq!(enclave, deserialized);
550 }
551
552 #[test]
553 fn vec_u8_should_be_encryptable_and_decryptable_with_password() {
554 let bytes = [0u8, 1u8, 2u8, 3u8, 4u8].to_vec();
555 let password = "my password".to_string();
556
557 let encrypted_bytes = bytes.encrypt(password.clone(), KeyDerivationStrategy::PBKDF2(10_000));
559 let decrypted_bytes = encrypted_bytes.decrypt(password);
560
561 assert!(decrypted_bytes.is_ok());
562 assert_eq!(decrypted_bytes.unwrap(), bytes);
563 }
564
565 #[test]
566 fn vec_u8_should_be_encryptable_and_decryptable_with_key() {
567 let bytes = [0u8, 1u8, 2u8, 3u8, 4u8].to_vec();
568 let key = [0u8; KEY_SIZE];
569
570 let encrypted_bytes = bytes.encrypt_with_raw_key(key);
571 let decrypted_bytes = encrypted_bytes.decrypt_with_key(key);
572
573 assert!(decrypted_bytes.is_ok());
574 assert_eq!(decrypted_bytes.unwrap(), bytes);
575 }
576
577 #[test]
578 fn vec_u8_should_be_encryptable_and_decryptable_with_metadata() {
579 let bytes = [0u8, 1u8, 2u8, 3u8, 4u8].to_vec();
580 let key = [0u8; KEY_SIZE];
581
582 let encrypted_bytes = bytes.encrypt_with_metadata(key, b"metadata".to_vec());
583 let decrypted_bytes = encrypted_bytes.decrypt_with_metadata::<Vec<u8>>(key);
584
585 assert!(decrypted_bytes.is_ok());
586 assert_eq!(decrypted_bytes.unwrap(), (bytes, b"metadata".to_vec()));
587 }
588
589 #[test]
590 fn strings_should_be_encryptable_and_decryptable_with_password() {
591 let string = "my string".to_string();
592 let password = "my password".to_string();
593
594 let encrypted_bytes = string.encrypt(password.clone(), KeyDerivationStrategy::PBKDF2(10_000));
596 let decrypted_bytes = encrypted_bytes.decrypt(password);
597
598 assert!(decrypted_bytes.is_ok());
599 assert_eq!(decrypted_bytes.unwrap(), string.as_bytes());
600 }
601 }
602}