diff options
| author | Jack O'Connor <[email protected]> | 2020-02-03 10:13:32 -0500 |
|---|---|---|
| committer | Jack O'Connor <[email protected]> | 2020-02-03 10:18:02 -0500 |
| commit | 9ffe377d454f8f3fbb289370b3b8ad916e33779d (patch) | |
| tree | 54105075e857cdd1ca412384b648865aea5f6fb3 /src/traits.rs | |
| parent | bcd424cab664923656b1c7d5c94ba9482fe7834f (diff) | |
implement crypto_mac::Mac
Diffstat (limited to 'src/traits.rs')
| -rw-r--r-- | src/traits.rs | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/src/traits.rs b/src/traits.rs new file mode 100644 index 0000000..0d9279d --- /dev/null +++ b/src/traits.rs @@ -0,0 +1,122 @@ +//! Implementations for commonly used traits like `digest::Digest` and +//! `crypto_mac::Mac`. + +use crate::{Hasher, OutputReader}; +use digest::generic_array::{ + typenum::{U32, U64}, + GenericArray, +}; + +impl digest::BlockInput for Hasher { + type BlockSize = U64; +} + +impl digest::Input for Hasher { + fn input<B: AsRef<[u8]>>(&mut self, data: B) { + self.update(data.as_ref()); + } +} + +impl digest::Reset for Hasher { + fn reset(&mut self) { + self.reset(); // the inherent method + } +} + +impl digest::FixedOutput for Hasher { + type OutputSize = U32; + + fn fixed_result(self) -> GenericArray<u8, Self::OutputSize> { + GenericArray::clone_from_slice(self.finalize().as_bytes()) + } +} + +impl digest::ExtendableOutput for Hasher { + type Reader = OutputReader; + + fn xof_result(self) -> Self::Reader { + self.finalize_xof() + } +} + +impl digest::XofReader for OutputReader { + fn read(&mut self, buffer: &mut [u8]) { + self.fill(buffer); + } +} + +impl crypto_mac::Mac for Hasher { + type OutputSize = U32; + type KeySize = U32; + + fn new(key: &GenericArray<u8, Self::KeySize>) -> Self { + let key_bytes: [u8; 32] = (*key).into(); + Hasher::new_keyed(&key_bytes) + } + + fn input(&mut self, data: &[u8]) { + self.update(data); + } + + fn reset(&mut self) { + self.reset(); + } + + fn result(self) -> crypto_mac::MacResult<Self::OutputSize> { + crypto_mac::MacResult::new((*self.finalize().as_bytes()).into()) + } +} + +#[cfg(test)] +mod test { + #[test] + fn test_digest_traits() { + // Inherent methods. + let mut hasher1 = crate::Hasher::new(); + hasher1.update(b"foo"); + hasher1.update(b"bar"); + hasher1.update(b"baz"); + let out1 = hasher1.finalize(); + let mut xof1 = [0; 301]; + hasher1.finalize_xof().fill(&mut xof1); + assert_eq!(out1.as_bytes(), &xof1[..32]); + + // Trait implementations. + let mut hasher2: crate::Hasher = digest::Digest::new(); + digest::Digest::input(&mut hasher2, b"xxx"); + digest::Digest::reset(&mut hasher2); // avoid the reset() inherent method + digest::Digest::input(&mut hasher2, b"foo"); + digest::Digest::input(&mut hasher2, b"bar"); + digest::Digest::input(&mut hasher2, b"baz"); + let out2 = digest::Digest::result(hasher2.clone()); + let mut xof2 = [0; 301]; + digest::XofReader::read( + &mut digest::ExtendableOutput::xof_result(hasher2), + &mut xof2, + ); + assert_eq!(out1.as_bytes(), &out2[..]); + assert_eq!(xof1[..], xof2[..]); + } + + #[test] + fn test_mac_trait() { + // Inherent methods. + let key = b"some super secret key bytes fooo"; + let mut hasher1 = crate::Hasher::new_keyed(key); + hasher1.update(b"foo"); + hasher1.update(b"bar"); + hasher1.update(b"baz"); + let out1 = hasher1.finalize(); + + // Trait implementation. + let generic_key = (*key).into(); + let mut hasher2: crate::Hasher = crypto_mac::Mac::new(&generic_key); + crypto_mac::Mac::input(&mut hasher2, b"xxx"); + crypto_mac::Mac::reset(&mut hasher2); + crypto_mac::Mac::input(&mut hasher2, b"foo"); + crypto_mac::Mac::input(&mut hasher2, b"bar"); + crypto_mac::Mac::input(&mut hasher2, b"baz"); + let out2 = crypto_mac::Mac::result(hasher2); + assert_eq!(out1.as_bytes(), out2.code().as_slice()); + } +} |
