solana_hmac_sha256/
lib.rs1use solana_nostd_sha256::{hashv, HASH_LENGTH};
2
3#[derive(Clone, Debug)]
7pub struct HmacSha256 {
8 outer_key_pad: [u8; 64],
9 inner_key_pad: [u8; 64],
10 digest: Vec<u8>,
11}
12
13const BLOCK_SIZE: usize = 64;
14
15impl HmacSha256 {
16 pub fn new(key: &[u8]) -> Self {
17 let mut key_block = [0u8; BLOCK_SIZE];
18
19 if key.len() > BLOCK_SIZE {
20 let hashed_key = hashv(&[key]);
21 key_block[..HASH_LENGTH].copy_from_slice(&hashed_key);
22 for i in HASH_LENGTH..BLOCK_SIZE {
23 key_block[i] = 0;
24 }
25 } else {
26 key_block[..key.len()].copy_from_slice(key);
27 }
28
29 let mut inner_key_pad = [0u8; BLOCK_SIZE];
30 let mut outer_key_pad = [0u8; BLOCK_SIZE];
31
32 for i in 0..BLOCK_SIZE {
33 inner_key_pad[i] = key_block[i] ^ 0x36;
34 outer_key_pad[i] = key_block[i] ^ 0x5C;
35 }
36
37 let digest = inner_key_pad.to_vec();
38
39 Self {
40 digest,
41 outer_key_pad,
42 inner_key_pad,
43 }
44 }
45
46 #[inline(always)]
47 pub fn update(&mut self, data: &[u8]) {
48 self.digest.extend_from_slice(data);
49 }
50
51 #[inline(always)]
52 pub fn reset(&mut self) {
53 self.digest.clear();
54 self.digest.extend_from_slice(&self.inner_key_pad);
55 }
56
57 pub fn finalize(&self) -> [u8; 32] {
58 let inner_hash = hashv(&[&self.digest]);
59 hashv(&[&self.outer_key_pad, &inner_hash])
60 }
61
62 pub fn finalize_reset(&mut self) -> [u8; 32] {
63 let result = self.finalize();
64 self.reset();
65 result
66 }
67}
68
69pub fn hmac_sha256(key: &[u8], message: &[u8]) -> [u8; 32] {
73 let mut key_block = [0u8; BLOCK_SIZE];
74
75 if key.len() > BLOCK_SIZE {
76 let hashed_key = hashv(&[key]);
77 key_block[..HASH_LENGTH].copy_from_slice(&hashed_key);
78 for i in HASH_LENGTH..BLOCK_SIZE {
79 key_block[i] = 0;
80 }
81 } else {
82 key_block[..key.len()].copy_from_slice(key);
83 }
84
85 let mut inner_key_pad = [0u8; BLOCK_SIZE];
86 let mut outer_key_pad = [0u8; BLOCK_SIZE];
87
88 for i in 0..BLOCK_SIZE {
89 inner_key_pad[i] = key_block[i] ^ 0x36;
90 outer_key_pad[i] = key_block[i] ^ 0x5C;
91 }
92 let inner_hash = hashv(&[&inner_key_pad, message]);
93 hashv(&[&outer_key_pad, &inner_hash])
94}
95
96
97#[cfg(test)]
98mod tests {
99 use crate::{hmac_sha256, HmacSha256};
100
101 const HASH_TEST_TEST: [u8;32] = [0x88, 0xcd, 0x21, 0x08, 0xb5, 0x34, 0x7d, 0x97, 0x3c, 0xf3, 0x9c, 0xdf, 0x90, 0x53, 0xd7, 0xdd, 0x42, 0x70, 0x48, 0x76, 0xd8, 0xc9, 0xa9, 0xbd, 0x8e, 0x2d, 0x16, 0x82, 0x59, 0xd3, 0xdd, 0xf7];
102
103 #[test]
104 fn hmac_sha256_test() {
105 let h = hmac_sha256(b"test", b"test");
106 assert_eq!(h, HASH_TEST_TEST)
107 }
108
109 #[test]
110 fn hmac_sha256_digest_type(){
111 let mut h = HmacSha256::new(b"test");
112 h.update(b"test");
113 assert_eq!(h.finalize(), HASH_TEST_TEST)
114 }
115
116}