1use crate::sha256::{self, Sha256};
2
3const BLOCK_SIZE: usize = 64;
4
5#[derive(Clone)]
6pub struct HmacSha256 {
7 inner: Sha256,
8 outer: Sha256,
9}
10
11impl HmacSha256 {
12 pub fn new(key: &[u8]) -> Self {
13 let mut key_block = [0u8; BLOCK_SIZE];
14
15 if key.len() > BLOCK_SIZE {
16 let hashed = sha256::sha256(key);
17 key_block[..32].copy_from_slice(&hashed);
18 } else {
19 key_block[..key.len()].copy_from_slice(key);
20 }
21
22 let mut ipad = [0u8; BLOCK_SIZE];
23 let mut opad = [0u8; BLOCK_SIZE];
24 for i in 0..BLOCK_SIZE {
25 ipad[i] = key_block[i] ^ 0x36;
26 opad[i] = key_block[i] ^ 0x5C;
27 }
28
29 let mut inner = Sha256::new();
30 inner.update(&ipad);
31
32 let mut outer = Sha256::new();
33 outer.update(&opad);
34
35 HmacSha256 { inner, outer }
36 }
37
38 pub fn update(&mut self, data: &[u8]) {
39 self.inner.update(data);
40 }
41
42 pub fn finalize(&self) -> [u8; 32] {
43 let inner_digest = self.inner.digest();
44 let mut outer = self.outer.clone();
45 outer.update(&inner_digest);
46 outer.digest()
47 }
48}
49
50pub fn hmac_sha256(key: &[u8], data: &[u8]) -> [u8; 32] {
51 let mut h = HmacSha256::new(key);
52 h.update(data);
53 h.finalize()
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 fn hex_to_bytes(hex: &str) -> alloc::vec::Vec<u8> {
61 (0..hex.len())
62 .step_by(2)
63 .map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap())
64 .collect()
65 }
66
67 #[test]
68 fn test_hmac_rfc4231_test1() {
69 let key = hex_to_bytes("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
71 let data = b"Hi There";
72 let expected = hex_to_bytes("b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7");
73 assert_eq!(hmac_sha256(&key, data).to_vec(), expected);
74 }
75
76 #[test]
77 fn test_hmac_rfc4231_test2() {
78 let key = b"Jefe";
80 let data = b"what do ya want for nothing?";
81 let expected = hex_to_bytes("5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843");
82 assert_eq!(hmac_sha256(key, data).to_vec(), expected);
83 }
84
85 #[test]
86 fn test_hmac_empty_msg() {
87 let key = b"secret";
88 let result = hmac_sha256(key, b"");
89 assert_eq!(result.len(), 32);
91 }
92
93 #[test]
94 fn test_hmac_long_key() {
95 let key = [0xAA; 131];
97 let data = b"Test Using Larger Than Block-Size Key - Hash Key First";
98 let expected = hex_to_bytes("60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54");
99 assert_eq!(hmac_sha256(&key, data).to_vec(), expected);
100 }
101
102 #[test]
103 fn test_hmac_incremental() {
104 let key = b"key";
105 let data = b"hello world";
106 let expected = hmac_sha256(key, data);
107
108 let mut h = HmacSha256::new(key);
109 h.update(b"hello ");
110 h.update(b"world");
111 assert_eq!(h.finalize(), expected);
112 }
113}