1use std::iter::repeat;
12
13use cryptoutil;
14use digest::Digest;
15use mac::{Mac, MacResult};
16
17pub struct Hmac<D> {
21 digest: D,
22 i_key: Vec<u8>,
23 o_key: Vec<u8>,
24 finished: bool
25}
26
27fn derive_key(key: &mut [u8], mask: u8) {
28 for elem in key.iter_mut() {
29 *elem ^= mask;
30 }
31}
32
33fn expand_key<D: Digest>(digest: &mut D, key: &[u8]) -> Vec<u8> {
37 let bs = digest.block_size();
38 let mut expanded_key: Vec<u8> = repeat(0).take(bs).collect();
39
40 if key.len() <= bs {
41 cryptoutil::copy_memory(key, &mut expanded_key);
42 } else {
43 let output_size = digest.output_bytes();
44 digest.input(key);
45 digest.result(&mut expanded_key[..output_size]);
46 digest.reset();
47 }
48 expanded_key
49}
50
51fn create_keys<D: Digest>(digest: &mut D, key: &[u8]) -> (Vec<u8>, Vec<u8>) {
54 let mut i_key = expand_key(digest, key);
55 let mut o_key = i_key.clone();
56 derive_key(&mut i_key, 0x36);
57 derive_key(&mut o_key, 0x5c);
58 (i_key, o_key)
59}
60
61impl <D: Digest> Hmac<D> {
62 pub fn new(mut digest: D, key: &[u8]) -> Hmac<D> {
71 let (i_key, o_key) = create_keys(&mut digest, key);
72 digest.input(&i_key[..]);
73 Hmac {
74 digest: digest,
75 i_key: i_key,
76 o_key: o_key,
77 finished: false
78 }
79 }
80}
81
82impl <D: Digest> Mac for Hmac<D> {
83 fn input(&mut self, data: &[u8]) {
84 assert!(!self.finished);
85 self.digest.input(data);
86 }
87
88 fn reset(&mut self) {
89 self.digest.reset();
90 self.digest.input(&self.i_key[..]);
91 self.finished = false;
92 }
93
94 fn result(&mut self) -> MacResult {
95 let output_size = self.digest.output_bytes();
96 let mut code: Vec<u8> = repeat(0).take(output_size).collect();
97
98 self.raw_result(&mut code);
99
100 MacResult::new_from_owned(code)
101 }
102
103 fn raw_result(&mut self, output: &mut [u8]) {
104 if !self.finished {
105 self.digest.result(output);
106
107 self.digest.reset();
108 self.digest.input(&self.o_key[..]);
109 self.digest.input(output);
110
111 self.finished = true;
112 }
113
114 self.digest.result(output);
115 }
116
117 fn output_bytes(&self) -> usize { self.digest.output_bytes() }
118}
119
120#[cfg(test)]
121mod test {
122 use std::iter::repeat;
123
124 use mac::{Mac, MacResult};
125 use hmac::Hmac;
126 use digest::Digest;
127 use md5::Md5;
128
129 struct Test {
130 key: Vec<u8>,
131 data: Vec<u8>,
132 expected: Vec<u8>
133 }
134
135 fn tests() -> Vec<Test> {
138 vec![
139 Test {
140 key: repeat(0x0bu8).take(16).collect(),
141 data: b"Hi There".to_vec(),
142 expected: vec![
143 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
144 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d ]
145 },
146 Test {
147 key: b"Jefe".to_vec(),
148 data: b"what do ya want for nothing?".to_vec(),
149 expected: vec![
150 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
151 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 ]
152 },
153 Test {
154 key: repeat(0xaau8).take(16).collect(),
155 data: repeat(0xddu8).take(50).collect(),
156 expected: vec![
157 0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
158 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 ]
159 }
160 ]
161 }
162
163 #[test]
164 fn test_hmac_md5() {
165 let tests = tests();
166 for t in tests.iter() {
167 let mut hmac = Hmac::new(Md5::new(), &t.key[..]);
168
169 hmac.input(&t.data[..]);
170 let result = hmac.result();
171 let expected = MacResult::new(&t.expected[..]);
172 assert!(result == expected);
173
174 hmac.reset();
175
176 hmac.input(&t.data[..]);
177 let result2 = hmac.result();
178 let expected2 = MacResult::new(&t.expected[..]);
179 assert!(result2 == expected2);
180 }
181 }
182
183 #[test]
184 fn test_hmac_md5_incremental() {
185 let tests = tests();
186 for t in tests.iter() {
187 let mut hmac = Hmac::new(Md5::new(), &t.key[..]);
188 for i in 0..t.data.len() {
189 hmac.input(&t.data[i..i + 1]);
190 }
191 let result = hmac.result();
192 let expected = MacResult::new(&t.expected[..]);
193 assert!(result == expected);
194 }
195 }
196}