1use crate::{ContentFormat, CryptoError, EncString, KeyId, KeyIds, store::KeyStoreContext};
21
22pub trait CompositeEncryptable<Ids: KeyIds, Key: KeyId, Output> {
27 fn encrypt_composite(
30 &self,
31 ctx: &mut KeyStoreContext<Ids>,
32 key: Key,
33 ) -> Result<Output, CryptoError>;
34}
35
36impl<Ids: KeyIds, Key: KeyId, T: CompositeEncryptable<Ids, Key, Output>, Output>
37 CompositeEncryptable<Ids, Key, Option<Output>> for Option<T>
38{
39 fn encrypt_composite(
40 &self,
41 ctx: &mut KeyStoreContext<Ids>,
42 key: Key,
43 ) -> Result<Option<Output>, CryptoError> {
44 self.as_ref()
45 .map(|value| value.encrypt_composite(ctx, key))
46 .transpose()
47 }
48}
49
50impl<Ids: KeyIds, Key: KeyId, T: CompositeEncryptable<Ids, Key, Output>, Output>
51 CompositeEncryptable<Ids, Key, Vec<Output>> for Vec<T>
52{
53 fn encrypt_composite(
54 &self,
55 ctx: &mut KeyStoreContext<Ids>,
56 key: Key,
57 ) -> Result<Vec<Output>, CryptoError> {
58 self.iter()
59 .map(|value| value.encrypt_composite(ctx, key))
60 .collect()
61 }
62}
63
64pub trait PrimitiveEncryptable<Ids: KeyIds, Key: KeyId, Output> {
67 fn encrypt(&self, ctx: &mut KeyStoreContext<Ids>, key: Key) -> Result<Output, CryptoError>;
69}
70
71impl<Ids: KeyIds, Key: KeyId, T: PrimitiveEncryptable<Ids, Key, Output>, Output>
72 PrimitiveEncryptable<Ids, Key, Option<Output>> for Option<T>
73{
74 fn encrypt(
75 &self,
76 ctx: &mut KeyStoreContext<Ids>,
77 key: Key,
78 ) -> Result<Option<Output>, CryptoError> {
79 self.as_ref()
80 .map(|value| value.encrypt(ctx, key))
81 .transpose()
82 }
83}
84
85impl<Ids: KeyIds> PrimitiveEncryptable<Ids, Ids::Symmetric, EncString> for &str {
86 fn encrypt(
87 &self,
88 ctx: &mut KeyStoreContext<Ids>,
89 key: Ids::Symmetric,
90 ) -> Result<EncString, CryptoError> {
91 self.as_bytes().encrypt(ctx, key, ContentFormat::Utf8)
92 }
93}
94
95impl<Ids: KeyIds> PrimitiveEncryptable<Ids, Ids::Symmetric, EncString> for String {
96 fn encrypt(
97 &self,
98 ctx: &mut KeyStoreContext<Ids>,
99 key: Ids::Symmetric,
100 ) -> Result<EncString, CryptoError> {
101 self.as_bytes().encrypt(ctx, key, ContentFormat::Utf8)
102 }
103}
104
105pub(crate) trait PrimitiveEncryptableWithContentType<Ids: KeyIds, Key: KeyId, Output> {
108 fn encrypt(
110 &self,
111 ctx: &mut KeyStoreContext<Ids>,
112 key: Key,
113 content_format: ContentFormat,
114 ) -> Result<Output, CryptoError>;
115}
116
117impl<Ids: KeyIds> PrimitiveEncryptableWithContentType<Ids, Ids::Symmetric, EncString> for &[u8] {
118 fn encrypt(
119 &self,
120 ctx: &mut KeyStoreContext<Ids>,
121 key: Ids::Symmetric,
122 content_format: ContentFormat,
123 ) -> Result<EncString, CryptoError> {
124 ctx.encrypt_data_with_symmetric_key(key, self, content_format)
125 }
126}
127
128impl<Ids: KeyIds> PrimitiveEncryptableWithContentType<Ids, Ids::Symmetric, EncString> for Vec<u8> {
129 fn encrypt(
130 &self,
131 ctx: &mut KeyStoreContext<Ids>,
132 key: Ids::Symmetric,
133 content_format: ContentFormat,
134 ) -> Result<EncString, CryptoError> {
135 ctx.encrypt_data_with_symmetric_key(key, self, content_format)
136 }
137}
138
139impl<Ids: KeyIds, Key: KeyId, T: PrimitiveEncryptableWithContentType<Ids, Key, Output>, Output>
140 PrimitiveEncryptableWithContentType<Ids, Key, Option<Output>> for Option<T>
141{
142 fn encrypt(
143 &self,
144 ctx: &mut KeyStoreContext<Ids>,
145 key: Key,
146 content_format: crate::ContentFormat,
147 ) -> Result<Option<Output>, CryptoError> {
148 self.as_ref()
149 .map(|value| value.encrypt(ctx, key, content_format))
150 .transpose()
151 }
152}
153
154impl<Ids: KeyIds, Key: KeyId, T: PrimitiveEncryptableWithContentType<Ids, Key, Output>, Output>
155 PrimitiveEncryptableWithContentType<Ids, Key, Vec<Output>> for Vec<T>
156{
157 fn encrypt(
158 &self,
159 ctx: &mut KeyStoreContext<Ids>,
160 key: Key,
161 content_format: ContentFormat,
162 ) -> Result<Vec<Output>, CryptoError> {
163 self.iter()
164 .map(|value| value.encrypt(ctx, key, content_format))
165 .collect()
166 }
167}
168
169#[cfg(test)]
170mod tests {
171 use crate::{
172 AsymmetricCryptoKey, ContentFormat, Decryptable, KeyStore, PrimitiveEncryptable,
173 PublicKeyEncryptionAlgorithm, SymmetricKeyAlgorithm,
174 traits::{encryptable::PrimitiveEncryptableWithContentType, tests::*},
175 };
176
177 fn test_store() -> KeyStore<TestIds> {
178 let store = KeyStore::<TestIds>::default();
179
180 let asymm_key = AsymmetricCryptoKey::make(PublicKeyEncryptionAlgorithm::RsaOaepSha1);
181
182 let mut ctx = store.context_mut();
183 let local_key_id = ctx.make_symmetric_key(SymmetricKeyAlgorithm::Aes256CbcHmac);
184 ctx.persist_symmetric_key(local_key_id, TestSymmKey::A(0))
185 .unwrap();
186 #[allow(deprecated)]
187 ctx.set_asymmetric_key(TestAsymmKey::A(0), asymm_key.clone())
188 .unwrap();
189 drop(ctx);
190
191 store
192 }
193
194 #[test]
195 fn test_encryptable_bytes() {
196 let store = test_store();
197 let mut ctx = store.context();
198 let key = TestSymmKey::A(0);
199
200 let vec_data = vec![1, 2, 3, 4, 5];
201 let slice_data: &[u8] = &vec_data;
202
203 let vec_encrypted = vec_data
204 .encrypt(&mut ctx, key, ContentFormat::OctetStream)
205 .unwrap();
206 let slice_encrypted = slice_data
207 .encrypt(&mut ctx, key, ContentFormat::OctetStream)
208 .unwrap();
209
210 let vec_decrypted: Vec<u8> = vec_encrypted.decrypt(&mut ctx, key).unwrap();
211 let slice_decrypted: Vec<u8> = slice_encrypted.decrypt(&mut ctx, key).unwrap();
212
213 assert_eq!(vec_data, vec_decrypted);
214 assert_eq!(slice_data, slice_decrypted);
215 }
216
217 #[test]
218 fn test_encryptable_string() {
219 let store = test_store();
220 let mut ctx = store.context();
221 let key = TestSymmKey::A(0);
222
223 let string_data = "Hello, World!".to_string();
224 let str_data: &str = string_data.as_str();
225
226 let string_encrypted = string_data.encrypt(&mut ctx, key).unwrap();
227 let str_encrypted = str_data.encrypt(&mut ctx, key).unwrap();
228
229 let string_decrypted: String = string_encrypted.decrypt(&mut ctx, key).unwrap();
230 let str_decrypted: String = str_encrypted.decrypt(&mut ctx, key).unwrap();
231
232 assert_eq!(string_data, string_decrypted);
233 assert_eq!(str_data, str_decrypted);
234 }
235
236 #[test]
237 fn test_encryptable_option_some() {
238 let store = test_store();
239 let mut ctx = store.context();
240 let key = TestSymmKey::A(0);
241
242 let string_data = Some("Hello, World!".to_string());
243
244 let string_encrypted = string_data.encrypt(&mut ctx, key).unwrap();
245
246 let string_decrypted: Option<String> = string_encrypted.decrypt(&mut ctx, key).unwrap();
247
248 assert_eq!(string_data, string_decrypted);
249 }
250
251 #[test]
252 fn test_encryptable_option_none() {
253 let store = test_store();
254 let mut ctx = store.context();
255
256 let key = TestSymmKey::A(0);
257 let none_data: Option<String> = None;
258 let string_encrypted = none_data.encrypt(&mut ctx, key).unwrap();
259 assert_eq!(string_encrypted, None);
260
261 let bad_key = TestSymmKey::B((0, 1));
264 let string_encrypted_bad = none_data.encrypt(&mut ctx, bad_key).unwrap();
265 assert_eq!(string_encrypted_bad, None);
266 }
267}