1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
pub const SHA1_DIGEST_BYTES: usize = 20;
const SHA1_KEY_BYTES: usize = 64;
const INNER_PAD_BYTES: u8 = 0x36;
const OUTER_PAD_BYTE: u8 = 0x5c;
const KEY_PAD_BYTE: u8 = 0x00;
use sha1::{Digest, Sha1};
pub fn hmac_sha1(key: &[u8], message: &[u8], output: &mut [u8]) {
let mut sha1_ctx = Sha1::new();
let auth_key: &mut [u8; SHA1_KEY_BYTES] = &mut [KEY_PAD_BYTE; SHA1_KEY_BYTES];
if key.len() > SHA1_KEY_BYTES {
sha1_ctx.update(key);
let digest = sha1_ctx.finalize_reset();
auth_key[..SHA1_DIGEST_BYTES].copy_from_slice(&(digest));
} else {
auth_key[..key.len()].copy_from_slice(key);
}
let mut inner_padding: [u8; SHA1_KEY_BYTES] = [INNER_PAD_BYTES; SHA1_KEY_BYTES];
let mut outer_padding: [u8; SHA1_KEY_BYTES] = [OUTER_PAD_BYTE; SHA1_KEY_BYTES];
for (offset, elem) in auth_key.iter().enumerate() {
inner_padding[offset] ^= elem;
outer_padding[offset] ^= elem;
}
sha1_ctx.update(&inner_padding);
sha1_ctx.update(message);
let inner_hash = sha1_ctx.finalize_reset();
sha1_ctx.update(&outer_padding);
sha1_ctx.update(&inner_hash);
output.copy_from_slice(&sha1_ctx.finalize())
}
#[cfg(test)]
mod tests {
use super::hmac_sha1;
#[test]
fn test_vector1() {
let data = "Hi There".as_bytes();
let key = &[0x0b; 20];
let expected = "b617318655057264e28bc0b6fb378c8ef146be00".to_string();
let mut buf = [0_u8; 20];
hmac_sha1(key, data, &mut buf);
assert_eq!(hex::encode(buf), expected);
}
#[test]
fn test_vector2() {
let data = "what do ya want for nothing?".as_bytes();
let key = "Jefe".as_bytes();
let expected = "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79".to_string();
let mut buf = [0_u8; 20];
hmac_sha1(key, data, &mut buf);
assert_eq!(hex::encode(buf), expected);
}
#[test]
fn test_vector3() {
let data = &[0xdd; 50];
let key = &[0xaa; 20];
let expected = "125d7342b9ac11cd91a39af48aa17b4f63f175d3".to_string();
let mut buf = [0_u8; 20];
hmac_sha1(key, data, &mut buf);
assert_eq!(hex::encode(buf), expected);
}
#[test]
fn test_vector4() {
let data = &[0xcd; 50];
let key = &[
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25,
];
let expected = "4c9007f4026250c6bc8414f9bf50c86c2d7235da".to_string();
let mut buf = [0_u8; 20];
hmac_sha1(key, data, &mut buf);
assert_eq!(hex::encode(buf), expected);
}
}