/rust/registry/src/index.crates.io-1949cf8c6b5b557f/hmac-0.12.1/src/simple.rs
Line | Count | Source |
1 | | use super::{get_der_key, IPAD, OPAD}; |
2 | | use core::fmt; |
3 | | use digest::{ |
4 | | crypto_common::{Block, BlockSizeUser, InvalidLength, Key, KeySizeUser}, |
5 | | Digest, FixedOutput, KeyInit, MacMarker, Output, OutputSizeUser, Update, |
6 | | }; |
7 | | #[cfg(feature = "reset")] |
8 | | use digest::{FixedOutputReset, Reset}; |
9 | | |
10 | | /// Simplified HMAC instance able to operate over hash functions |
11 | | /// which do not expose block-level API and hash functions which |
12 | | /// process blocks lazily (e.g. BLAKE2). |
13 | | #[derive(Clone)] |
14 | | pub struct SimpleHmac<D: Digest + BlockSizeUser> { |
15 | | digest: D, |
16 | | opad_key: Block<D>, |
17 | | #[cfg(feature = "reset")] |
18 | | ipad_key: Block<D>, |
19 | | } |
20 | | |
21 | | impl<D: Digest + BlockSizeUser> KeySizeUser for SimpleHmac<D> { |
22 | | type KeySize = D::BlockSize; |
23 | | } |
24 | | |
25 | | impl<D: Digest + BlockSizeUser> MacMarker for SimpleHmac<D> {} |
26 | | |
27 | | impl<D: Digest + BlockSizeUser> KeyInit for SimpleHmac<D> { |
28 | 3.20k | fn new(key: &Key<Self>) -> Self { |
29 | 3.20k | Self::new_from_slice(key.as_slice()).unwrap() |
30 | 3.20k | } |
31 | | |
32 | | #[inline] |
33 | 12.8k | fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> { |
34 | 12.8k | let der_key = get_der_key::<D>(key); |
35 | 12.8k | let mut ipad_key = der_key.clone(); |
36 | 821k | for b in ipad_key.iter_mut() { |
37 | 821k | *b ^= IPAD; |
38 | 821k | } |
39 | 12.8k | let mut digest = D::new(); |
40 | 12.8k | digest.update(&ipad_key); |
41 | | |
42 | 12.8k | let mut opad_key = der_key; |
43 | 821k | for b in opad_key.iter_mut() { |
44 | 821k | *b ^= OPAD; |
45 | 821k | } |
46 | | |
47 | 12.8k | Ok(Self { |
48 | 12.8k | digest, |
49 | 12.8k | opad_key, |
50 | 12.8k | #[cfg(feature = "reset")] |
51 | 12.8k | ipad_key, |
52 | 12.8k | }) |
53 | 12.8k | } |
54 | | } |
55 | | |
56 | | impl<D: Digest + BlockSizeUser> Update for SimpleHmac<D> { |
57 | | #[inline(always)] |
58 | 51.3k | fn update(&mut self, data: &[u8]) { |
59 | 51.3k | self.digest.update(data); |
60 | 51.3k | } |
61 | | } |
62 | | |
63 | | impl<D: Digest + BlockSizeUser> OutputSizeUser for SimpleHmac<D> { |
64 | | type OutputSize = D::OutputSize; |
65 | | } |
66 | | |
67 | | impl<D: Digest + BlockSizeUser> FixedOutput for SimpleHmac<D> { |
68 | 6.41k | fn finalize_into(self, out: &mut Output<Self>) { |
69 | 6.41k | let mut h = D::new(); |
70 | 6.41k | h.update(&self.opad_key); |
71 | 6.41k | h.update(&self.digest.finalize()); |
72 | 6.41k | h.finalize_into(out); |
73 | 6.41k | } |
74 | | } |
75 | | |
76 | | impl<D: Digest + BlockSizeUser + fmt::Debug> fmt::Debug for SimpleHmac<D> { |
77 | | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
78 | | f.debug_struct("SimpleHmac") |
79 | | .field("digest", &self.digest) |
80 | | // TODO: replace with `finish_non_exhaustive` on MSRV |
81 | | // bump to 1.53 |
82 | | .field("..", &"..") |
83 | | .finish() |
84 | | } |
85 | | } |
86 | | |
87 | | #[cfg(feature = "reset")] |
88 | | #[cfg_attr(docsrs, doc(cfg(feature = "reset")))] |
89 | | impl<D: Digest + BlockSizeUser + Reset> Reset for SimpleHmac<D> { |
90 | | fn reset(&mut self) { |
91 | | Reset::reset(&mut self.digest); |
92 | | self.digest.update(&self.ipad_key); |
93 | | } |
94 | | } |
95 | | |
96 | | #[cfg(feature = "reset")] |
97 | | #[cfg_attr(docsrs, doc(cfg(feature = "reset")))] |
98 | | impl<D: Digest + BlockSizeUser + FixedOutputReset> FixedOutputReset for SimpleHmac<D> { |
99 | 16.0k | fn finalize_into_reset(&mut self, out: &mut Output<Self>) { |
100 | 16.0k | let mut h = D::new(); |
101 | 16.0k | Update::update(&mut h, &self.opad_key); |
102 | 16.0k | Update::update(&mut h, &self.digest.finalize_reset()); |
103 | 16.0k | Update::update(&mut self.digest, &self.ipad_key); |
104 | 16.0k | Digest::finalize_into(h, out); |
105 | 16.0k | } |
106 | | } |