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