1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
use digest::Digest; use generic_array::GenericArray; use Mac; const IPAD: u8 = 0x36; const OPAD: u8 = 0x5c; pub struct Hmac<T: Digest> { inner: T, outer: T, } impl<T: Digest + Default> Hmac<T> { pub fn new<K: AsRef<[u8]>>(key: K) -> Self { Self::with_digest(key.as_ref(), Default::default()) } } impl<T: Digest> Hmac<T> { pub fn with_digest(key: &[u8], digest: T) -> Self { let mut inner = digest.clone(); let mut outer = digest.clone(); let key = Self::expand_key(key, digest); for byte in key.iter() { inner.update(&[byte ^ IPAD]); outer.update(&[byte ^ OPAD]); } Hmac { inner: inner, outer: outer, } } fn expand_key(key: &[u8], mut digest: T) -> GenericArray<u8, T::BlockSize> { let bs = T::block_size(); let mut exp_key = GenericArray::new(); if key.len() <= bs { for i in 0..key.len() { exp_key[i] = key[i]; } } else { digest.update(key); digest.result(&mut exp_key[..]); } exp_key } } impl<T: Digest> Mac for Hmac<T> { fn update<D: AsRef<[u8]>>(&mut self, data: D) { self.inner.update(data) } fn output_bits() -> usize { T::output_bits() } fn block_size() -> usize { T::block_size() } fn result<O: AsMut<[u8]>>(mut self, mut output: O) { self.inner.result(output.as_mut()); self.outer.update(output.as_mut()); self.outer.result(output.as_mut()); } }