1 //! Implementations of commonly used traits like
2 //! [`digest::Digest`](https://crates.io/crates/digest) and
3 //! [`crypto_mac::Mac`](https://crates.io/crates/crypto-mac).
4 
5 pub use crypto_mac;
6 pub use digest;
7 
8 use crate::{Hasher, OutputReader};
9 use digest::generic_array::{
10     typenum::{U32, U64},
11     GenericArray,
12 };
13 
14 impl digest::BlockInput for Hasher {
15     type BlockSize = U64;
16 }
17 
18 impl digest::Update for Hasher {
19     #[inline]
update(&mut self, data: impl AsRef<[u8]>)20     fn update(&mut self, data: impl AsRef<[u8]>) {
21         self.update(data.as_ref());
22     }
23 }
24 
25 impl digest::Reset for Hasher {
26     #[inline]
reset(&mut self)27     fn reset(&mut self) {
28         self.reset(); // the inherent method
29     }
30 }
31 
32 impl digest::FixedOutput for Hasher {
33     type OutputSize = U32;
34 
35     #[inline]
finalize_into(self, out: &mut GenericArray<u8, Self::OutputSize>)36     fn finalize_into(self, out: &mut GenericArray<u8, Self::OutputSize>) {
37         out.copy_from_slice(self.finalize().as_bytes());
38     }
39 
40     #[inline]
finalize_into_reset(&mut self, out: &mut GenericArray<u8, Self::OutputSize>)41     fn finalize_into_reset(&mut self, out: &mut GenericArray<u8, Self::OutputSize>) {
42         out.copy_from_slice(self.finalize().as_bytes());
43         self.reset();
44     }
45 }
46 
47 impl digest::ExtendableOutput for Hasher {
48     type Reader = OutputReader;
49 
50     #[inline]
finalize_xof(self) -> Self::Reader51     fn finalize_xof(self) -> Self::Reader {
52         Hasher::finalize_xof(&self)
53     }
54 
55     #[inline]
finalize_xof_reset(&mut self) -> Self::Reader56     fn finalize_xof_reset(&mut self) -> Self::Reader {
57         let reader = Hasher::finalize_xof(self);
58         self.reset();
59         reader
60     }
61 }
62 
63 impl digest::XofReader for OutputReader {
64     #[inline]
read(&mut self, buffer: &mut [u8])65     fn read(&mut self, buffer: &mut [u8]) {
66         self.fill(buffer);
67     }
68 }
69 
70 impl crypto_mac::NewMac for Hasher {
71     type KeySize = U32;
72 
73     #[inline]
new(key: &crypto_mac::Key<Self>) -> Self74     fn new(key: &crypto_mac::Key<Self>) -> Self {
75         let key_bytes: [u8; 32] = (*key).into();
76         Hasher::new_keyed(&key_bytes)
77     }
78 }
79 
80 impl crypto_mac::Mac for Hasher {
81     type OutputSize = U32;
82 
83     #[inline]
update(&mut self, data: &[u8])84     fn update(&mut self, data: &[u8]) {
85         self.update(data);
86     }
87 
88     #[inline]
reset(&mut self)89     fn reset(&mut self) {
90         self.reset();
91     }
92 
93     #[inline]
finalize(self) -> crypto_mac::Output<Self>94     fn finalize(self) -> crypto_mac::Output<Self> {
95         crypto_mac::Output::new(digest::Digest::finalize(self))
96     }
97 }
98 
99 #[cfg(test)]
100 mod test {
101     use super::*;
102 
103     #[test]
test_digest_traits()104     fn test_digest_traits() {
105         // Inherent methods.
106         let mut hasher1 = crate::Hasher::new();
107         hasher1.update(b"foo");
108         hasher1.update(b"bar");
109         hasher1.update(b"baz");
110         let out1 = hasher1.finalize();
111         let mut xof1 = [0; 301];
112         hasher1.finalize_xof().fill(&mut xof1);
113         assert_eq!(out1.as_bytes(), &xof1[..32]);
114 
115         // Trait implementations.
116         let mut hasher2: crate::Hasher = digest::Digest::new();
117         digest::Digest::update(&mut hasher2, b"xxx");
118         digest::Digest::reset(&mut hasher2);
119         digest::Digest::update(&mut hasher2, b"foo");
120         digest::Digest::update(&mut hasher2, b"bar");
121         digest::Digest::update(&mut hasher2, b"baz");
122         let out2 = digest::Digest::finalize(hasher2.clone());
123         let mut xof2 = [0; 301];
124         digest::XofReader::read(
125             &mut digest::ExtendableOutput::finalize_xof(hasher2.clone()),
126             &mut xof2,
127         );
128         assert_eq!(out1.as_bytes(), &out2[..]);
129         assert_eq!(xof1[..], xof2[..]);
130 
131         // Again with the resetting variants.
132         let mut hasher3: crate::Hasher = digest::Digest::new();
133         digest::Digest::update(&mut hasher3, b"foobarbaz");
134         let mut out3 = [0; 32];
135         digest::FixedOutput::finalize_into_reset(
136             &mut hasher3,
137             GenericArray::from_mut_slice(&mut out3),
138         );
139         digest::Digest::update(&mut hasher3, b"foobarbaz");
140         let mut out4 = [0; 32];
141         digest::FixedOutput::finalize_into_reset(
142             &mut hasher3,
143             GenericArray::from_mut_slice(&mut out4),
144         );
145         digest::Digest::update(&mut hasher3, b"foobarbaz");
146         let mut xof3 = [0; 301];
147         digest::XofReader::read(
148             &mut digest::ExtendableOutput::finalize_xof_reset(&mut hasher3),
149             &mut xof3,
150         );
151         digest::Digest::update(&mut hasher3, b"foobarbaz");
152         let mut xof4 = [0; 301];
153         digest::XofReader::read(
154             &mut digest::ExtendableOutput::finalize_xof_reset(&mut hasher3),
155             &mut xof4,
156         );
157         assert_eq!(out1.as_bytes(), &out3[..]);
158         assert_eq!(out1.as_bytes(), &out4[..]);
159         assert_eq!(xof1[..], xof3[..]);
160         assert_eq!(xof1[..], xof4[..]);
161     }
162 
163     #[test]
test_mac_trait()164     fn test_mac_trait() {
165         // Inherent methods.
166         let key = b"some super secret key bytes fooo";
167         let mut hasher1 = crate::Hasher::new_keyed(key);
168         hasher1.update(b"foo");
169         hasher1.update(b"bar");
170         hasher1.update(b"baz");
171         let out1 = hasher1.finalize();
172 
173         // Trait implementation.
174         let generic_key = (*key).into();
175         let mut hasher2: crate::Hasher = crypto_mac::NewMac::new(&generic_key);
176         crypto_mac::Mac::update(&mut hasher2, b"xxx");
177         crypto_mac::Mac::reset(&mut hasher2);
178         crypto_mac::Mac::update(&mut hasher2, b"foo");
179         crypto_mac::Mac::update(&mut hasher2, b"bar");
180         crypto_mac::Mac::update(&mut hasher2, b"baz");
181         let out2 = crypto_mac::Mac::finalize(hasher2);
182         assert_eq!(out1.as_bytes(), out2.into_bytes().as_slice());
183     }
184 }
185