bitwarden_crypto/keys/
key_encryptable.rs

1use std::{collections::HashMap, hash::Hash, sync::Arc};
2
3use rayon::prelude::*;
4use uuid::Uuid;
5
6use crate::{error::Result, ContentFormat, CryptoError, SymmetricCryptoKey};
7
8#[allow(missing_docs)]
9pub trait KeyContainer: Send + Sync {
10    fn get_key(&self, org_id: &Option<Uuid>) -> Result<&SymmetricCryptoKey, CryptoError>;
11}
12
13impl<T: KeyContainer> KeyContainer for Arc<T> {
14    fn get_key(&self, org_id: &Option<Uuid>) -> Result<&SymmetricCryptoKey, CryptoError> {
15        self.as_ref().get_key(org_id)
16    }
17}
18
19#[allow(missing_docs)]
20pub trait CryptoKey {}
21
22/// An encryption operation that takes the input value and encrypts it into the output value
23/// using a key reference. Implementing this requires a content type to be specified in
24/// the implementation.
25pub trait KeyEncryptable<Key: CryptoKey, Output> {
26    /// Encrypts a value using the provided key reference.
27    fn encrypt_with_key(self, key: &Key) -> Result<Output>;
28}
29
30/// An encryption operation that takes the input value and encrypts it into the output value
31/// using a key reference, with an externally provided content type.
32///
33/// In contrast to `KeyEncryptable`, this trait allows the caller to specify the content format.
34/// Because of this, it is not exposed outside of the crate, because outside callers should
35/// not make a choice about the content format. Where possible, the content format is
36/// ensured at compile time by the type system, not at runtime by the caller passing
37/// in a parameter.
38pub(crate) trait KeyEncryptableWithContentType<Key: CryptoKey, Output> {
39    fn encrypt_with_key(self, key: &Key, content_format: ContentFormat) -> Result<Output>;
40}
41
42#[allow(missing_docs)]
43pub trait KeyDecryptable<Key: CryptoKey, Output> {
44    fn decrypt_with_key(&self, key: &Key) -> Result<Output>;
45}
46
47impl<T: KeyEncryptable<Key, Output>, Key: CryptoKey, Output> KeyEncryptable<Key, Option<Output>>
48    for Option<T>
49{
50    fn encrypt_with_key(self, key: &Key) -> Result<Option<Output>> {
51        self.map(|e| e.encrypt_with_key(key)).transpose()
52    }
53}
54
55impl<T: KeyDecryptable<Key, Output>, Key: CryptoKey, Output> KeyDecryptable<Key, Option<Output>>
56    for Option<T>
57{
58    fn decrypt_with_key(&self, key: &Key) -> Result<Option<Output>> {
59        self.as_ref().map(|e| e.decrypt_with_key(key)).transpose()
60    }
61}
62
63impl<T: KeyEncryptable<Key, Output>, Key: CryptoKey, Output> KeyEncryptable<Key, Output>
64    for Box<T>
65{
66    fn encrypt_with_key(self, key: &Key) -> Result<Output> {
67        (*self).encrypt_with_key(key)
68    }
69}
70
71impl<T: KeyDecryptable<Key, Output>, Key: CryptoKey, Output> KeyDecryptable<Key, Output>
72    for Box<T>
73{
74    fn decrypt_with_key(&self, key: &Key) -> Result<Output> {
75        (**self).decrypt_with_key(key)
76    }
77}
78
79impl<
80        T: KeyEncryptable<Key, Output> + Send + Sync,
81        Key: CryptoKey + Send + Sync,
82        Output: Send + Sync,
83    > KeyEncryptable<Key, Vec<Output>> for Vec<T>
84{
85    fn encrypt_with_key(self, key: &Key) -> Result<Vec<Output>> {
86        self.into_par_iter()
87            .map(|e| e.encrypt_with_key(key))
88            .collect()
89    }
90}
91
92impl<
93        T: KeyDecryptable<Key, Output> + Send + Sync,
94        Key: CryptoKey + Send + Sync,
95        Output: Send + Sync,
96    > KeyDecryptable<Key, Vec<Output>> for Vec<T>
97{
98    fn decrypt_with_key(&self, key: &Key) -> Result<Vec<Output>> {
99        self.into_par_iter()
100            .map(|e| e.decrypt_with_key(key))
101            .collect()
102    }
103}
104
105impl<
106        T: KeyEncryptable<Key, Output> + Send + Sync,
107        Key: CryptoKey + Send + Sync,
108        Output: Send + Sync,
109        Id: Hash + Eq + Send + Sync,
110    > KeyEncryptable<Key, HashMap<Id, Output>> for HashMap<Id, T>
111{
112    fn encrypt_with_key(self, key: &Key) -> Result<HashMap<Id, Output>> {
113        self.into_par_iter()
114            .map(|(id, e)| Ok((id, e.encrypt_with_key(key)?)))
115            .collect()
116    }
117}
118
119impl<
120        T: KeyDecryptable<Key, Output> + Send + Sync,
121        Key: CryptoKey + Send + Sync,
122        Output: Send + Sync,
123        Id: Hash + Eq + Copy + Send + Sync,
124    > KeyDecryptable<Key, HashMap<Id, Output>> for HashMap<Id, T>
125{
126    fn decrypt_with_key(&self, key: &Key) -> Result<HashMap<Id, Output>> {
127        self.into_par_iter()
128            .map(|(id, e)| Ok((*id, e.decrypt_with_key(key)?)))
129            .collect()
130    }
131}