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