Skip to main content

vitaminc_protected/
digest.rs

1use std::marker::PhantomData;
2
3use crate::{Acceptable, Controlled, DefaultScope, Scope};
4use digest::array::Array;
5use digest::Digest;
6use digest::FixedOutputReset;
7use digest::Output;
8use digest::OutputSizeUser;
9use digest::Reset;
10
11pub struct ProtectedDigest<D, InputScope = DefaultScope>(D, PhantomData<InputScope>);
12
13// TODO: Implement Usage scopes
14// TODO: How can we force that the Digest types have Zeroize enabled? (Its a feature in the digest crate but in the 0.11.0.pre versions)
15impl<D: Digest, InputScope: Scope> ProtectedDigest<D, InputScope> {
16    pub fn new() -> Self {
17        Self(D::new(), PhantomData)
18    }
19
20    pub fn new_with_prefix<T>(data: &T) -> Self
21    where
22        T: Controlled + Acceptable<InputScope>,
23        T::Inner: AsRef<[u8]>,
24    {
25        Self(D::new_with_prefix(data.risky_ref()), PhantomData)
26    }
27
28    pub fn update<T>(&mut self, data: &T)
29    where
30        T: Controlled + Acceptable<InputScope>,
31        T::Inner: AsRef<[u8]>,
32    {
33        self.0.update(data.risky_ref())
34    }
35
36    pub fn finalize<T>(self) -> T
37    where
38        T: Controlled + From<Array<u8, <D as OutputSizeUser>::OutputSize>>,
39    {
40        let result = self.0.finalize();
41        result.into()
42    }
43
44    pub fn finalize_into<'m, T>(self, out: &'m mut T)
45    where
46        T: Controlled,
47        &'m mut Array<u8, <D as OutputSizeUser>::OutputSize>: From<&'m mut T::Inner>,
48    {
49        let target: &mut Output<D> = out.inner_mut().into();
50        self.0.finalize_into(target);
51    }
52
53    pub fn finalize_reset<T>(&mut self) -> T
54    where
55        D: FixedOutputReset,
56        T: Controlled + From<Array<u8, <D as OutputSizeUser>::OutputSize>>,
57    {
58        let result = self.0.finalize_reset();
59        result.into()
60    }
61
62    pub fn finalize_into_reset<'m, T>(&'m mut self, out: &'m mut T)
63    where
64        D: FixedOutputReset,
65        T: Controlled,
66        &'m mut Array<u8, <D as OutputSizeUser>::OutputSize>: From<&'m mut T::Inner>,
67    {
68        let target: &mut Output<D> = out.inner_mut().into();
69        Digest::finalize_into_reset(&mut self.0, target);
70    }
71
72    pub fn reset(&mut self)
73    where
74        D: Reset,
75    {
76        Digest::reset(&mut self.0);
77    }
78
79    pub fn output_size() -> usize {
80        <D as Digest>::output_size()
81    }
82
83    pub fn digest<T, O>(data: &T) -> O
84    where
85        T: Controlled + Acceptable<InputScope>,
86        T::Inner: AsRef<[u8]>,
87        O: Controlled + From<Array<u8, <D as OutputSizeUser>::OutputSize>>,
88    {
89        let mut hasher = Self::new();
90        hasher.update(data);
91        hasher.finalize()
92    }
93}
94
95impl<D: Digest, InputScope: Scope> Default for ProtectedDigest<D, InputScope> {
96    fn default() -> Self {
97        Self::new()
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104    use crate::Protected;
105    use sha2::{Sha256, Sha384};
106
107    #[test]
108    fn test_digest_sha256_finalize() {
109        let mut digest: ProtectedDigest<Sha256> = ProtectedDigest::new();
110        digest.update(&Protected::new([0u8; 32]));
111        let result: Protected<[u8; 32]> = digest.finalize();
112        assert_eq!(
113            result.risky_unwrap(),
114            [
115                102, 104, 122, 173, 248, 98, 189, 119, 108, 143, 193, 139, 142, 159, 142, 32, 8,
116                151, 20, 133, 110, 226, 51, 179, 144, 42, 89, 29, 13, 95, 41, 37
117            ]
118        );
119    }
120
121    #[test]
122    fn test_digest_sha256_finalize_into() {
123        let mut digest: ProtectedDigest<Sha256> = ProtectedDigest::new();
124        digest.update(&Protected::new([0u8; 32]));
125        let mut result = Protected::new([0u8; 32]);
126        digest.finalize_into(&mut result);
127        assert_eq!(
128            result.risky_unwrap(),
129            [
130                102, 104, 122, 173, 248, 98, 189, 119, 108, 143, 193, 139, 142, 159, 142, 32, 8,
131                151, 20, 133, 110, 226, 51, 179, 144, 42, 89, 29, 13, 95, 41, 37
132            ]
133        );
134    }
135
136    #[test]
137    fn test_digest_sha384() {
138        let mut digest: ProtectedDigest<Sha384> = ProtectedDigest::new();
139        digest.update(&Protected::new([0u8; 32]));
140        let result: Protected<[u8; 48]> = digest.finalize();
141        assert_eq!(
142            result.risky_unwrap(),
143            [
144                163, 143, 255, 75, 162, 108, 21, 228, 172, 156, 222, 140, 3, 16, 58, 200, 144, 128,
145                253, 71, 84, 95, 222, 148, 70, 200, 241, 146, 114, 158, 171, 123, 208, 58, 77, 92,
146                49, 135, 247, 95, 226, 167, 27, 14, 229, 10, 74, 64,
147            ]
148        );
149    }
150}