1use hmac::Mac;
2
3#[derive(Clone)]
4pub struct HmacSha256 {
5 inner: hmac::Hmac<sha2::Sha256>,
6}
7
8impl HmacSha256 {
9 pub fn new(key: &[u8]) -> Self {
10 HmacSha256 {
11 inner: hmac::Hmac::<sha2::Sha256>::new_from_slice(key)
12 .expect("HMAC accepts any key length"),
13 }
14 }
15
16 pub fn update(&mut self, data: &[u8]) {
17 self.inner.update(data);
18 }
19
20 pub fn finalize(&self) -> [u8; 32] {
21 self.inner.clone().finalize().into_bytes().into()
22 }
23}
24
25pub fn hmac_sha256(key: &[u8], data: &[u8]) -> [u8; 32] {
26 let mut h = HmacSha256::new(key);
27 h.update(data);
28 h.finalize()
29}
30
31#[cfg(test)]
32mod tests {
33 use super::*;
34
35 fn hex_to_bytes(hex: &str) -> alloc::vec::Vec<u8> {
36 (0..hex.len())
37 .step_by(2)
38 .map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap())
39 .collect()
40 }
41
42 #[test]
43 fn test_hmac_rfc4231_test1() {
44 let key = hex_to_bytes("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
45 let data = b"Hi There";
46 let expected =
47 hex_to_bytes("b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7");
48 assert_eq!(hmac_sha256(&key, data).to_vec(), expected);
49 }
50
51 #[test]
52 fn test_hmac_rfc4231_test2() {
53 let key = b"Jefe";
54 let data = b"what do ya want for nothing?";
55 let expected =
56 hex_to_bytes("5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843");
57 assert_eq!(hmac_sha256(key, data).to_vec(), expected);
58 }
59
60 #[test]
61 fn test_hmac_empty_msg() {
62 let key = b"secret";
63 let result = hmac_sha256(key, b"");
64 assert_eq!(result.len(), 32);
65 }
66
67 #[test]
68 fn test_hmac_long_key() {
69 let key = [0xAA; 131];
70 let data = b"Test Using Larger Than Block-Size Key - Hash Key First";
71 let expected =
72 hex_to_bytes("60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54");
73 assert_eq!(hmac_sha256(&key, data).to_vec(), expected);
74 }
75
76 #[test]
77 fn test_hmac_incremental() {
78 let key = b"key";
79 let data = b"hello world";
80 let expected = hmac_sha256(key, data);
81
82 let mut h = HmacSha256::new(key);
83 h.update(b"hello ");
84 h.update(b"world");
85 assert_eq!(h.finalize(), expected);
86 }
87}