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