1use core::{borrow, fmt, ops, str};
12
13#[cfg(feature = "serde")]
14use serde::{Deserialize, Deserializer, Serialize, Serializer};
15
16use crate::{FromSliceError, Hash, HashEngine};
17
18#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
20#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
21#[cfg_attr(feature = "schemars", schemars(transparent))]
22#[repr(transparent)]
23pub struct Hmac<T: Hash>(T);
24
25impl<T: Hash + str::FromStr> str::FromStr for Hmac<T> {
26 type Err = <T as str::FromStr>::Err;
27 fn from_str(s: &str) -> Result<Self, Self::Err> { Ok(Hmac(str::FromStr::from_str(s)?)) }
28}
29
30pub struct HmacMidState<T: Hash> {
32 pub inner: <T::Engine as HashEngine>::MidState,
34 pub outer: <T::Engine as HashEngine>::MidState,
36}
37
38#[derive(Clone)]
40pub struct HmacEngine<T: Hash> {
41 iengine: T::Engine,
42 oengine: T::Engine,
43}
44
45impl<T: Hash> Default for HmacEngine<T> {
46 fn default() -> Self { HmacEngine::new(&[]) }
47}
48
49impl<T: Hash> HmacEngine<T> {
50 pub fn new(key: &[u8]) -> HmacEngine<T> {
58 debug_assert!(T::Engine::BLOCK_SIZE <= 128);
59
60 let mut ipad = [0x36u8; 128];
61 let mut opad = [0x5cu8; 128];
62 let mut ret = HmacEngine { iengine: <T as Hash>::engine(), oengine: <T as Hash>::engine() };
63
64 if key.len() > T::Engine::BLOCK_SIZE {
65 let hash = <T as Hash>::hash(key);
66 for (b_i, b_h) in ipad.iter_mut().zip(&hash[..]) {
67 *b_i ^= *b_h;
68 }
69 for (b_o, b_h) in opad.iter_mut().zip(&hash[..]) {
70 *b_o ^= *b_h;
71 }
72 } else {
73 for (b_i, b_h) in ipad.iter_mut().zip(key) {
74 *b_i ^= *b_h;
75 }
76 for (b_o, b_h) in opad.iter_mut().zip(key) {
77 *b_o ^= *b_h;
78 }
79 };
80
81 HashEngine::input(&mut ret.iengine, &ipad[..T::Engine::BLOCK_SIZE]);
82 HashEngine::input(&mut ret.oengine, &opad[..T::Engine::BLOCK_SIZE]);
83 ret
84 }
85
86 pub fn from_inner_engines(iengine: T::Engine, oengine: T::Engine) -> HmacEngine<T> {
88 HmacEngine { iengine, oengine }
89 }
90}
91
92impl<T: Hash> HashEngine for HmacEngine<T> {
93 type MidState = HmacMidState<T>;
94
95 fn midstate(&self) -> Self::MidState {
96 HmacMidState { inner: self.iengine.midstate(), outer: self.oengine.midstate() }
97 }
98
99 const BLOCK_SIZE: usize = T::Engine::BLOCK_SIZE;
100
101 fn n_bytes_hashed(&self) -> usize { self.iengine.n_bytes_hashed() }
102
103 fn input(&mut self, buf: &[u8]) { self.iengine.input(buf) }
104}
105
106impl<T: Hash> fmt::Debug for Hmac<T> {
107 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.0, f) }
108}
109
110impl<T: Hash> fmt::Display for Hmac<T> {
111 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
112}
113
114impl<T: Hash> fmt::LowerHex for Hmac<T> {
115 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
116}
117
118impl<T: Hash> ops::Index<usize> for Hmac<T> {
119 type Output = u8;
120 fn index(&self, index: usize) -> &u8 { &self.0[index] }
121}
122
123impl<T: Hash> ops::Index<ops::Range<usize>> for Hmac<T> {
124 type Output = [u8];
125 fn index(&self, index: ops::Range<usize>) -> &[u8] { &self.0[index] }
126}
127
128impl<T: Hash> ops::Index<ops::RangeFrom<usize>> for Hmac<T> {
129 type Output = [u8];
130 fn index(&self, index: ops::RangeFrom<usize>) -> &[u8] { &self.0[index] }
131}
132
133impl<T: Hash> ops::Index<ops::RangeTo<usize>> for Hmac<T> {
134 type Output = [u8];
135 fn index(&self, index: ops::RangeTo<usize>) -> &[u8] { &self.0[index] }
136}
137
138impl<T: Hash> ops::Index<ops::RangeFull> for Hmac<T> {
139 type Output = [u8];
140 fn index(&self, index: ops::RangeFull) -> &[u8] { &self.0[index] }
141}
142
143impl<T: Hash> borrow::Borrow<[u8]> for Hmac<T> {
144 fn borrow(&self) -> &[u8] { &self[..] }
145}
146
147impl<T: Hash> Hash for Hmac<T> {
148 type Engine = HmacEngine<T>;
149 type Bytes = T::Bytes;
150
151 fn from_engine(mut e: HmacEngine<T>) -> Hmac<T> {
152 let ihash = T::from_engine(e.iengine);
153 e.oengine.input(&ihash[..]);
154 let ohash = T::from_engine(e.oengine);
155 Hmac(ohash)
156 }
157
158 const LEN: usize = T::LEN;
159
160 fn from_slice(sl: &[u8]) -> Result<Hmac<T>, FromSliceError> { T::from_slice(sl).map(Hmac) }
161
162 fn to_byte_array(self) -> Self::Bytes { self.0.to_byte_array() }
163
164 fn as_byte_array(&self) -> &Self::Bytes { self.0.as_byte_array() }
165
166 fn from_byte_array(bytes: T::Bytes) -> Self { Hmac(T::from_byte_array(bytes)) }
167
168 fn all_zeros() -> Self {
169 let zeros = T::all_zeros();
170 Hmac(zeros)
171 }
172}
173
174#[cfg(feature = "serde")]
175impl<T: Hash + Serialize> Serialize for Hmac<T> {
176 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
177 Serialize::serialize(&self.0, s)
178 }
179}
180
181#[cfg(feature = "serde")]
182impl<'de, T: Hash + Deserialize<'de>> Deserialize<'de> for Hmac<T> {
183 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Hmac<T>, D::Error> {
184 let bytes = Deserialize::deserialize(d)?;
185 Ok(Hmac(bytes))
186 }
187}
188
189#[cfg(test)]
190mod tests {
191 #[test]
192 #[cfg(feature = "alloc")]
193 fn test() {
194 use crate::{sha256, Hash, HashEngine, Hmac, HmacEngine};
195
196 #[derive(Clone)]
197 struct Test {
198 key: Vec<u8>,
199 input: Vec<u8>,
200 output: Vec<u8>,
201 }
202
203 #[rustfmt::skip]
204 let tests = vec![
205 Test {
209 key: vec![ 0x0b; 20],
210 input: vec![0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65],
211 output: vec![
212 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53,
213 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
214 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7,
215 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7,
216 ],
217 },
218 Test {
219 key: vec![ 0x4a, 0x65, 0x66, 0x65 ],
220 input: vec![
221 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
222 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
223 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
224 0x69, 0x6e, 0x67, 0x3f,
225 ],
226 output: vec![
227 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
228 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
229 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
230 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43,
231 ],
232 },
233 Test {
234 key: vec![ 0xaa; 20 ],
235 input: vec![ 0xdd; 50 ],
236 output: vec![
237 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46,
238 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7,
239 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22,
240 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe,
241 ],
242 },
243 Test {
244 key: vec![
245 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
246 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
247 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
248 0x19
249 ],
250 input: vec![ 0xcd; 50 ],
251 output: vec![
252 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e,
253 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a,
254 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07,
255 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b,
256 ],
257 },
258 Test {
259 key: vec! [ 0xaa; 131 ],
260 input: vec![
261 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
262 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,
263 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
264 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,
265 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
266 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,
267 0x20, 0x46, 0x69, 0x72, 0x73, 0x74,
268 ],
269 output: vec![
270 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f,
271 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
272 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14,
273 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54,
274 ],
275 },
276 Test {
277 key: vec! [ 0xaa; 131 ],
278 input: vec![
279 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
280 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75,
281 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
282 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68,
283 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
284 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65,
285 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
286 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74,
287 0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
288 0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64,
289 0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
290 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65,
291 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
292 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20,
293 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
294 0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65,
295 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
296 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c,
297 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e,
298 ],
299 output: vec![
300 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb,
301 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44,
302 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93,
303 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2,
304 ],
305 },
306 ];
307
308 for test in tests {
309 let mut engine = HmacEngine::<sha256::Hash>::new(&test.key);
310 engine.input(&test.input);
311 let hash = Hmac::<sha256::Hash>::from_engine(engine);
312 assert_eq!(&hash[..], &test.output[..]);
313 assert_eq!(hash.as_byte_array(), test.output.as_slice());
314 }
315 }
316
317 #[cfg(feature = "serde")]
318 #[test]
319 fn hmac_sha512_serde() {
320 use serde_test::{assert_tokens, Configure, Token};
321
322 use crate::{sha512, Hash, Hmac};
323
324 #[rustfmt::skip]
325 static HASH_BYTES: [u8; 64] = [
326 0x8b, 0x41, 0xe1, 0xb7, 0x8a, 0xd1, 0x15, 0x21,
327 0x11, 0x3c, 0x52, 0xff, 0x18, 0x2a, 0x1b, 0x8e,
328 0x0a, 0x19, 0x57, 0x54, 0xaa, 0x52, 0x7f, 0xcd,
329 0x00, 0xa4, 0x11, 0x62, 0x0b, 0x46, 0xf2, 0x0f,
330 0xff, 0xfb, 0x80, 0x88, 0xcc, 0xf8, 0x54, 0x97,
331 0x12, 0x1a, 0xd4, 0x49, 0x9e, 0x08, 0x45, 0xb8,
332 0x76, 0xf6, 0xdd, 0x66, 0x40, 0x08, 0x8a, 0x2f,
333 0x0b, 0x2d, 0x8a, 0x60, 0x0b, 0xdf, 0x4c, 0x0c,
334 ];
335
336 let hash = Hmac::<sha512::Hash>::from_slice(&HASH_BYTES).expect("right number of bytes");
337 assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]);
338 assert_tokens(
339 &hash.readable(),
340 &[Token::Str(
341 "8b41e1b78ad11521113c52ff182a1b8e0a195754aa527fcd00a411620b46f20f\
342 fffb8088ccf85497121ad4499e0845b876f6dd6640088a2f0b2d8a600bdf4c0c",
343 )],
344 );
345 }
346}
347
348#[cfg(bench)]
349mod benches {
350 use test::Bencher;
351
352 use crate::{sha256, Hash, HashEngine, Hmac};
353
354 #[bench]
355 pub fn hmac_sha256_10(bh: &mut Bencher) {
356 let mut engine = Hmac::<sha256::Hash>::engine();
357 let bytes = [1u8; 10];
358 bh.iter(|| {
359 engine.input(&bytes);
360 });
361 bh.bytes = bytes.len() as u64;
362 }
363
364 #[bench]
365 pub fn hmac_sha256_1k(bh: &mut Bencher) {
366 let mut engine = Hmac::<sha256::Hash>::engine();
367 let bytes = [1u8; 1024];
368 bh.iter(|| {
369 engine.input(&bytes);
370 });
371 bh.bytes = bytes.len() as u64;
372 }
373
374 #[bench]
375 pub fn hmac_sha256_64k(bh: &mut Bencher) {
376 let mut engine = Hmac::<sha256::Hash>::engine();
377 let bytes = [1u8; 65536];
378 bh.iter(|| {
379 engine.input(&bytes);
380 });
381 bh.bytes = bytes.len() as u64;
382 }
383}