1use crate::utils::{IPAD, OPAD, get_der_key};
2use core::fmt;
3use digest::{
4 Digest, FixedOutput, KeyInit, MacMarker, Output, OutputSizeUser, Update,
5 common::{Block, BlockSizeUser, InvalidLength, Key, KeySizeUser},
6};
7use digest::{FixedOutputReset, Reset};
8
9#[derive(Clone)]
13pub struct SimpleHmacReset<D: Digest + BlockSizeUser> {
14 digest: D,
15 opad_key: Block<D>,
16 ipad_key: Block<D>,
17}
18
19impl<D: Digest + BlockSizeUser> KeySizeUser for SimpleHmacReset<D> {
20 type KeySize = D::BlockSize;
21}
22
23impl<D: Digest + BlockSizeUser> MacMarker for SimpleHmacReset<D> {}
24
25impl<D: Digest + BlockSizeUser> KeyInit for SimpleHmacReset<D> {
26 fn new(key: &Key<Self>) -> Self {
27 Self::new_from_slice(key.as_slice()).unwrap()
28 }
29
30 #[inline]
31 fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
32 let der_key = get_der_key::<D>(key);
33
34 let mut ipad_key = der_key.clone();
35 ipad_key.iter_mut().for_each(|b: &mut u8| *b ^= IPAD);
36
37 let mut digest = D::new();
38 digest.update(&ipad_key);
39
40 let mut opad_key = der_key;
41 opad_key.iter_mut().for_each(|b: &mut u8| *b ^= OPAD);
42
43 Ok(Self {
44 digest,
45 opad_key,
46 ipad_key,
47 })
48 }
49}
50
51impl<D: Digest + BlockSizeUser> Update for SimpleHmacReset<D> {
52 #[inline(always)]
53 fn update(&mut self, data: &[u8]) {
54 self.digest.update(data);
55 }
56}
57
58impl<D: Digest + BlockSizeUser> OutputSizeUser for SimpleHmacReset<D> {
59 type OutputSize = D::OutputSize;
60}
61
62impl<D: Digest + BlockSizeUser> FixedOutput for SimpleHmacReset<D> {
63 fn finalize_into(self, out: &mut Output<Self>) {
64 let mut h = D::new();
65 h.update(&self.opad_key);
66 h.update(self.digest.finalize());
67 h.finalize_into(out);
68 }
69}
70
71impl<D: Digest + BlockSizeUser + fmt::Debug> fmt::Debug for SimpleHmacReset<D> {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 f.write_str("SimpleResetHmac")
74 }
75}
76
77impl<D: Digest + BlockSizeUser + Reset> Reset for SimpleHmacReset<D> {
78 fn reset(&mut self) {
79 Reset::reset(&mut self.digest);
80 self.digest.update(&self.ipad_key);
81 }
82}
83
84impl<D: Digest + BlockSizeUser + FixedOutputReset> FixedOutputReset for SimpleHmacReset<D> {
85 fn finalize_into_reset(&mut self, out: &mut Output<Self>) {
86 let mut h = D::new();
87 Update::update(&mut h, &self.opad_key);
88 Update::update(&mut h, &self.digest.finalize_reset());
89 Update::update(&mut self.digest, &self.ipad_key);
90 Digest::finalize_into(h, out);
91 }
92}