Skip to main content

rns_crypto/
hmac.rs

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        // RFC 4231 Test Case 1
70        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        // RFC 4231 Test Case 2 - "Jefe" key
79        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        // Just verify it produces a 32-byte result without panicking
90        assert_eq!(result.len(), 32);
91    }
92
93    #[test]
94    fn test_hmac_long_key() {
95        // Key > 64 bytes should be hashed first
96        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}