1use crate::sha256::{BLOCK_SIZE, DIGEST_SIZE, SHA256};
10
11pub struct HMac {
32 inner: SHA256,
33 outer: SHA256,
34}
35
36impl HMac {
39 pub fn new(key: &[u8]) -> HMac {
47 if key.len() > BLOCK_SIZE {
75 let mut tmp = SHA256::new();
76 tmp.update(key);
77 return HMac::new(&tmp.digest());
78 }
79
80 let mut block: [u8; BLOCK_SIZE] = [0; BLOCK_SIZE];
81
82 let mut inner = SHA256::new();
83 let mut outer = SHA256::new();
84
85 block[..key.len()].copy_from_slice(key);
86
87 for elem in block.iter_mut() {
88 *elem ^= 0x36;
89 }
90 inner.update(&block);
91
92 for elem in block.iter_mut() {
94 *elem ^= 0x36 ^ 0x5c;
95 }
96 outer.update(&block);
97
98 HMac { inner, outer }
99 }
100
101 pub fn update(self: &mut HMac, data: &[u8]) {
105 self.inner.update(data);
106 }
107
108 pub fn digest(self: &mut HMac) -> [u8; DIGEST_SIZE] {
112 self.outer.update(&self.inner.digest());
113 self.outer.digest()
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 fn check(key: &[u8], inputs: &[&[u8]], expected: [u8; DIGEST_SIZE]) {
122 let mut hmac = HMac::new(key);
123
124 for chunk in inputs {
125 hmac.update(chunk);
126 }
127 assert_eq!(hmac.digest(), expected);
128 }
129
130 #[test]
135 fn it_should_compute_digest_for_vec0() {
136 check(
137 b"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
138 &[b"Hi There"],
139 [
140 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b,
141 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
142 0x2e, 0x32, 0xcf, 0xf7,
143 ],
144 );
145 }
146
147 #[test]
148 fn it_should_compute_digest_for_vec1() {
149 check(
150 b"Jefe",
151 &[b"what do ya want ", b"for nothing?"],
152 [
153 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95,
154 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9,
155 0x64, 0xec, 0x38, 0x43,
156 ],
157 );
158 }
159
160 #[test]
161 fn it_should_compute_digest_for_vec2() {
162 check(
163 &[
164 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
165 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
166 ],
167 &[
168 &[
169 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
170 0xdd, 0xdd, 0xdd,
171 ],
172 &[
173 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
174 0xdd, 0xdd, 0xdd,
175 ],
176 &[
177 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
178 0xdd, 0xdd, 0xdd,
179 ],
180 &[0xdd, 0xdd],
181 ],
182 [
183 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91,
184 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14,
185 0xce, 0xd5, 0x65, 0xfe,
186 ],
187 );
188 }
189
190 #[test]
191 fn it_should_compute_digest_for_vec3() {
192 check(
193 &[
194 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
195 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
196 ],
197 &[
198 &[
199 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
200 0xcd, 0xcd, 0xcd,
201 ],
202 &[
203 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
204 0xcd, 0xcd, 0xcd,
205 ],
206 &[
207 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
208 0xcd, 0xcd, 0xcd,
209 ],
210 &[0xcd, 0xcd],
211 ],
212 [
213 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2,
214 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4,
215 0x67, 0x29, 0x66, 0x5b,
216 ],
217 );
218 }
219
220 #[test]
221 fn it_should_compute_digest_for_vec4() {
222 check(
223 &[
224 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
225 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
226 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
227 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
228 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
229 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
230 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
231 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
232 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
233 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
234 ],
235 &[
236 b"Test Using Large",
237 b"r Than Block-Siz",
238 b"e Key - Hash Key",
239 b" First",
240 ],
241 [
242 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5,
243 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f,
244 0x0e, 0xe3, 0x7f, 0x54,
245 ],
246 );
247 }
248
249 #[test]
250 fn it_should_compute_digest_for_vec5() {
251 check(
252 &[
253 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
254 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
255 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
256 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
257 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
258 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
259 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
260 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
261 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
262 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
263 ],
264 &[
265 b"This is a test u",
266 b"sing a larger th",
267 b"an block-size ke",
268 b"y and a larger t",
269 b"han block-size d",
270 b"ata. The key nee",
271 b"ds to be hashed ",
272 b"before being use",
273 b"d by the HMAC al",
274 b"gorithm.",
275 ],
276 [
277 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0,
278 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53,
279 0x5c, 0x3a, 0x35, 0xe2,
280 ],
281 );
282 }
283
284 #[test]
289 fn it_should_compute_pbkdf2_stage_properly() {
290 check(
291 &[0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64],
292 &[&[
293 0xc6, 0x00, 0x40, 0x4e, 0x39, 0xc9, 0xe9, 0x7a, 0x7d, 0x7a, 0x74, 0x5b, 0x32, 0xc3,
294 0xe7, 0x42, 0x63, 0x87, 0xb3, 0x65, 0x69, 0x3c, 0x7f, 0x59, 0x30, 0x0f, 0xd8, 0xa0,
295 0x3a, 0xab, 0x4c, 0x6e,
296 ]],
297 [
298 0xbe, 0x97, 0xc8, 0x11, 0x49, 0x75, 0x0f, 0x47, 0x65, 0x9a, 0x37, 0xf6, 0x23, 0x00,
299 0x43, 0xf5, 0x79, 0xb5, 0xd8, 0x35, 0xac, 0xdd, 0xfc, 0x8e, 0x70, 0xd7, 0x4a, 0xef,
300 0x66, 0x95, 0xe1, 0x28,
301 ],
302 );
303 }
304}