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