bitwarden_crypto/traits/
encryptable.rs

1use crate::{store::KeyStoreContext, CryptoError, EncString, KeyId, KeyIds};
2
3/// An encryption operation that takes the input value and encrypts it into the output value.
4/// Implementations should generally consist of calling [Encryptable::encrypt] for all the fields of
5/// the type.
6pub trait Encryptable<Ids: KeyIds, Key: KeyId, Output> {
7    fn encrypt(&self, ctx: &mut KeyStoreContext<Ids>, key: Key) -> Result<Output, CryptoError>;
8}
9
10impl<Ids: KeyIds> Encryptable<Ids, Ids::Symmetric, EncString> for &[u8] {
11    fn encrypt(
12        &self,
13        ctx: &mut KeyStoreContext<Ids>,
14        key: Ids::Symmetric,
15    ) -> Result<EncString, CryptoError> {
16        ctx.encrypt_data_with_symmetric_key(key, self)
17    }
18}
19
20impl<Ids: KeyIds> Encryptable<Ids, Ids::Symmetric, EncString> for Vec<u8> {
21    fn encrypt(
22        &self,
23        ctx: &mut KeyStoreContext<Ids>,
24        key: Ids::Symmetric,
25    ) -> Result<EncString, CryptoError> {
26        ctx.encrypt_data_with_symmetric_key(key, self)
27    }
28}
29
30impl<Ids: KeyIds> Encryptable<Ids, Ids::Symmetric, EncString> for &str {
31    fn encrypt(
32        &self,
33        ctx: &mut KeyStoreContext<Ids>,
34        key: Ids::Symmetric,
35    ) -> Result<EncString, CryptoError> {
36        self.as_bytes().encrypt(ctx, key)
37    }
38}
39
40impl<Ids: KeyIds> Encryptable<Ids, Ids::Symmetric, EncString> for String {
41    fn encrypt(
42        &self,
43        ctx: &mut KeyStoreContext<Ids>,
44        key: Ids::Symmetric,
45    ) -> Result<EncString, CryptoError> {
46        self.as_bytes().encrypt(ctx, key)
47    }
48}
49
50impl<Ids: KeyIds, Key: KeyId, T: Encryptable<Ids, Key, Output>, Output>
51    Encryptable<Ids, Key, Option<Output>> for Option<T>
52{
53    fn encrypt(
54        &self,
55        ctx: &mut KeyStoreContext<Ids>,
56        key: Key,
57    ) -> Result<Option<Output>, CryptoError> {
58        self.as_ref()
59            .map(|value| value.encrypt(ctx, key))
60            .transpose()
61    }
62}
63
64impl<Ids: KeyIds, Key: KeyId, T: Encryptable<Ids, Key, Output>, Output>
65    Encryptable<Ids, Key, Vec<Output>> for Vec<T>
66{
67    fn encrypt(
68        &self,
69        ctx: &mut KeyStoreContext<Ids>,
70        key: Key,
71    ) -> Result<Vec<Output>, CryptoError> {
72        self.iter().map(|value| value.encrypt(ctx, key)).collect()
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use crate::{
79        traits::tests::*, AsymmetricCryptoKey, Decryptable, Encryptable, KeyStore,
80        SymmetricCryptoKey,
81    };
82
83    fn test_store() -> KeyStore<TestIds> {
84        let store = KeyStore::<TestIds>::default();
85
86        let symm_key = SymmetricCryptoKey::make_aes256_cbc_hmac_key();
87        let asymm_key = AsymmetricCryptoKey::generate(&mut rand::thread_rng());
88
89        #[allow(deprecated)]
90        store
91            .context_mut()
92            .set_symmetric_key(TestSymmKey::A(0), symm_key.clone())
93            .unwrap();
94        #[allow(deprecated)]
95        store
96            .context_mut()
97            .set_asymmetric_key(TestAsymmKey::A(0), asymm_key.clone())
98            .unwrap();
99
100        store
101    }
102
103    #[test]
104    fn test_encryptable_bytes() {
105        let store = test_store();
106        let mut ctx = store.context();
107        let key = TestSymmKey::A(0);
108
109        let vec_data = vec![1, 2, 3, 4, 5];
110        let slice_data: &[u8] = &vec_data;
111
112        let vec_encrypted = vec_data.encrypt(&mut ctx, key).unwrap();
113        let slice_encrypted = slice_data.encrypt(&mut ctx, key).unwrap();
114
115        let vec_decrypted: Vec<u8> = vec_encrypted.decrypt(&mut ctx, key).unwrap();
116        let slice_decrypted: Vec<u8> = slice_encrypted.decrypt(&mut ctx, key).unwrap();
117
118        assert_eq!(vec_data, vec_decrypted);
119        assert_eq!(slice_data, slice_decrypted);
120    }
121
122    #[test]
123    fn test_encryptable_string() {
124        let store = test_store();
125        let mut ctx = store.context();
126        let key = TestSymmKey::A(0);
127
128        let string_data = "Hello, World!".to_string();
129        let str_data: &str = string_data.as_str();
130
131        let string_encrypted = string_data.encrypt(&mut ctx, key).unwrap();
132        let str_encrypted = str_data.encrypt(&mut ctx, key).unwrap();
133
134        let string_decrypted: String = string_encrypted.decrypt(&mut ctx, key).unwrap();
135        let str_decrypted: String = str_encrypted.decrypt(&mut ctx, key).unwrap();
136
137        assert_eq!(string_data, string_decrypted);
138        assert_eq!(str_data, str_decrypted);
139    }
140
141    #[test]
142    fn test_encryptable_option_some() {
143        let store = test_store();
144        let mut ctx = store.context();
145        let key = TestSymmKey::A(0);
146
147        let string_data = Some("Hello, World!".to_string());
148
149        let string_encrypted = string_data.encrypt(&mut ctx, key).unwrap();
150
151        let string_decrypted: Option<String> = string_encrypted.decrypt(&mut ctx, key).unwrap();
152
153        assert_eq!(string_data, string_decrypted);
154    }
155
156    #[test]
157    fn test_encryptable_option_none() {
158        let store = test_store();
159        let mut ctx = store.context();
160
161        let key = TestSymmKey::A(0);
162        let none_data: Option<String> = None;
163        let string_encrypted = none_data.encrypt(&mut ctx, key).unwrap();
164        assert_eq!(string_encrypted, None);
165
166        // The None implementation will not do any decrypt operations, so it won't fail even if the
167        // key doesn't exist
168        let bad_key = TestSymmKey::B((0, 1));
169        let string_encrypted_bad = none_data.encrypt(&mut ctx, bad_key).unwrap();
170        assert_eq!(string_encrypted_bad, None);
171    }
172}