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