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
extern crate hmacsha1;
use std::fmt;
pub fn hotp(desired_code_length: usize, key: &[u8], counter: &[u8]) -> HotpOutput {
let hmac_value = hmacsha1::hmac_sha1(key, counter);
let dbc = sbits(&hmac_value);
HotpOutput{ code: dbc % 10u32.pow(desired_code_length as u32), length: desired_code_length }
}
fn offset(b: &[u8]) -> usize {
(b.last().unwrap() & 0xf) as usize
}
fn sbits(bits: &[u8]) -> u32 {
let offset = offset(bits);
let mut val: u32 = 0;
val += bits[offset + 3] as u32;
val += (bits[offset + 2] as u32) << 8;
val += (bits[offset + 1] as u32) << 16;
val += ((bits[offset] as u32) & 0x7f) << 24;
val
}
pub struct HotpOutput {
pub code: u32,
pub length: usize,
}
impl fmt::Display for HotpOutput {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:0length$}", self.code, length = self.length)
}
}