1use crate::{aad::IntoAad, cipher::Unspecified, Cipher, LocalCipherText};
2use vitaminc_protected::{Controlled, Protected};
3use zeroize::Zeroize;
4
5pub trait Decrypt: Sized {
6 type Encrypted;
7
8 fn decrypt<C>(encrypted: Self::Encrypted, cipher: &C) -> Result<Self, Unspecified>
9 where
10 C: Cipher,
11 {
12 Self::decrypt_with_aad(encrypted, cipher, ())
13 }
14
15 fn decrypt_with_aad<'a, C, A>(
16 encrypted: Self::Encrypted,
17 cipher: &C,
18 aad: A,
19 ) -> Result<Self, Unspecified>
20 where
21 C: Cipher,
22 A: IntoAad<'a>;
23}
24
25impl Decrypt for Vec<u8> {
26 type Encrypted = LocalCipherText;
27
28 fn decrypt_with_aad<'a, C, A>(
29 encrypted: Self::Encrypted,
30 cipher: &C,
31 aad: A,
32 ) -> Result<Self, Unspecified>
33 where
34 C: Cipher,
35 A: IntoAad<'a>,
36 {
37 cipher.decrypt_vec(encrypted, aad)
38 }
39}
40
41impl<const N: usize> Decrypt for [u8; N] {
42 type Encrypted = LocalCipherText;
43
44 fn decrypt_with_aad<'a, C, A>(
45 encrypted: Self::Encrypted,
46 cipher: &C,
47 aad: A,
48 ) -> Result<Self, Unspecified>
49 where
50 C: Cipher,
51 A: IntoAad<'a>,
52 {
53 let mut result_vec = cipher.decrypt_vec(encrypted, aad)?;
54 if result_vec.len() != N {
55 result_vec.zeroize();
57 return Err(Unspecified);
58 }
59 result_vec.try_into().map_err(|_| Unspecified)
60 }
61}
62
63impl Decrypt for String {
64 type Encrypted = LocalCipherText;
65
66 fn decrypt_with_aad<'a, C, A>(
67 encrypted: Self::Encrypted,
68 cipher: &C,
69 aad: A,
70 ) -> Result<Self, Unspecified>
71 where
72 C: Cipher,
73 A: IntoAad<'a>,
74 {
75 let bytes = cipher.decrypt_vec(encrypted, aad)?;
76 String::from_utf8(bytes).map_err(|_| Unspecified)
77 }
78}
79
80impl<T> Decrypt for Protected<T>
81where
82 Self: Controlled,
83 <Protected<T> as Controlled>::Inner: Decrypt,
84{
85 type Encrypted = <<Protected<T> as Controlled>::Inner as Decrypt>::Encrypted;
86
87 fn decrypt_with_aad<'a, C, A>(
88 encrypted: Self::Encrypted,
89 cipher: &C,
90 aad: A,
91 ) -> Result<Self, Unspecified>
92 where
93 C: Cipher,
94 A: IntoAad<'a>,
95 {
96 let inner = <Protected<T> as Controlled>::Inner::decrypt_with_aad(encrypted, cipher, aad)?;
97 Ok(Protected::init_from_inner(inner))
98 }
99}