bitwarden_crypto/traits/
decryptable.rs1use tracing::instrument;
2
3use crate::{CryptoError, EncString, KeyId, KeyIds, store::KeyStoreContext};
4
5pub trait Decryptable<Ids: KeyIds, Key: KeyId, Output> {
9 #[allow(missing_docs)]
10 fn decrypt(&self, ctx: &mut KeyStoreContext<Ids>, key: Key) -> Result<Output, CryptoError>;
11}
12
13impl<Ids: KeyIds> Decryptable<Ids, Ids::Symmetric, Vec<u8>> for EncString {
14 #[instrument(err, skip_all)]
15 fn decrypt(
16 &self,
17 ctx: &mut KeyStoreContext<Ids>,
18 key: Ids::Symmetric,
19 ) -> Result<Vec<u8>, CryptoError> {
20 ctx.decrypt_data_with_symmetric_key(key, self)
21 }
22}
23
24impl<Ids: KeyIds> Decryptable<Ids, Ids::Symmetric, String> for EncString {
25 #[instrument(err, skip_all)]
26 fn decrypt(
27 &self,
28 ctx: &mut KeyStoreContext<Ids>,
29 key: Ids::Symmetric,
30 ) -> Result<String, CryptoError> {
31 let bytes: Vec<u8> = self.decrypt(ctx, key)?;
32 String::from_utf8(bytes).map_err(|_| CryptoError::InvalidUtf8String)
33 }
34}
35
36impl<Ids: KeyIds, Key: KeyId, T: Decryptable<Ids, Key, Output>, Output>
37 Decryptable<Ids, Key, Option<Output>> for Option<T>
38{
39 fn decrypt(
40 &self,
41 ctx: &mut KeyStoreContext<Ids>,
42 key: Key,
43 ) -> Result<Option<Output>, CryptoError> {
44 self.as_ref()
45 .map(|value| value.decrypt(ctx, key))
46 .transpose()
47 }
48}
49
50impl<Ids: KeyIds, Key: KeyId, T: Decryptable<Ids, Key, Output>, Output>
51 Decryptable<Ids, Key, Vec<Output>> for Vec<T>
52{
53 fn decrypt(
54 &self,
55 ctx: &mut KeyStoreContext<Ids>,
56 key: Key,
57 ) -> Result<Vec<Output>, CryptoError> {
58 self.iter().map(|value| value.decrypt(ctx, key)).collect()
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use crate::{Decryptable, EncString, KeyStore, SymmetricCryptoKey, traits::tests::*};
65
66 fn test_store() -> KeyStore<TestIds> {
67 let store = KeyStore::<TestIds>::default();
68
69 let key = SymmetricCryptoKey::try_from("sJnO8rVi0dTwND43n0T9x7665s8mVUYNAaJ4nm7gx1iia1I7947URL60nwfIHaf9QJePO4VkNN0oT9jh4iC6aA==".to_string()).unwrap();
70
71 #[allow(deprecated)]
72 store
73 .context_mut()
74 .set_symmetric_key(TestSymmKey::A(0), key.clone())
75 .unwrap();
76
77 store
78 }
79
80 #[test]
81 fn test_decryptable_bytes() {
82 let store = test_store();
83 let mut ctx = store.context();
84 let key = TestSymmKey::A(0);
85
86 let data_encrypted: EncString = "2.kTtIypq9OLzd5iMMbU11pQ==|J4i3hTtGVdg7EZ+AQv/ujg==|QJpSpotQVpIW8j8dR/8l015WJzAIxBaOmrz4Uj/V1JA=".parse().unwrap();
87
88 let data_decrypted: Vec<u8> = data_encrypted.decrypt(&mut ctx, key).unwrap();
89 assert_eq!(data_decrypted, &[1, 2, 3, 4, 5]);
90 }
91
92 #[test]
93 fn test_decryptable_string() {
94 let store = test_store();
95 let mut ctx = store.context();
96 let key = TestSymmKey::A(0);
97
98 let data_encrypted: EncString = "2.fkvl0+sL1lwtiOn1eewsvQ==|dT0TynLl8YERZ8x7dxC+DQ==|cWhiRSYHOi/AA2LiV/JBJWbO9C7pbUpOM6TMAcV47hE=".parse().unwrap();
99
100 let data_decrypted: String = data_encrypted.decrypt(&mut ctx, key).unwrap();
101 assert_eq!(data_decrypted, "Hello, World!");
102 }
103
104 #[test]
105 fn test_decryptable_option_some() {
106 let store = test_store();
107 let mut ctx = store.context();
108 let key = TestSymmKey::A(0);
109
110 let data_encrypted: EncString = "2.fkvl0+sL1lwtiOn1eewsvQ==|dT0TynLl8YERZ8x7dxC+DQ==|cWhiRSYHOi/AA2LiV/JBJWbO9C7pbUpOM6TMAcV47hE=".parse().unwrap();
111 let data_encrypted_some = Some(data_encrypted);
112
113 let string_decrypted: Option<String> = data_encrypted_some.decrypt(&mut ctx, key).unwrap();
114 assert_eq!(string_decrypted, Some("Hello, World!".to_string()));
115 }
116
117 #[test]
118 fn test_decryptable_option_none() {
119 let store = test_store();
120 let mut ctx = store.context();
121
122 let key = TestSymmKey::A(0);
123 let none_data: Option<EncString> = None;
124 let string_decrypted: Option<String> = none_data.decrypt(&mut ctx, key).unwrap();
125 assert_eq!(string_decrypted, None);
126
127 let bad_key = TestSymmKey::B((0, 1));
130 let string_decrypted_bad: Option<String> = none_data.decrypt(&mut ctx, bad_key).unwrap();
131 assert_eq!(string_decrypted_bad, None);
132 }
133}