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