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
use crate::{calc_digest, decode_secret, encode_digest};
use crate::{Algorithm, OTP, TOTP};
use anyhow::Result;
pub static HOTP_DEFAULT_COUNTER: u32 = 1;
pub struct HOTP {
pub algorithm: Algorithm,
pub digits: u32,
pub secret: String,
}
impl OTP for HOTP {
fn compute(&self, counter: u64) -> Result<String> {
let decoded = decode_secret(&self.secret)?;
let digest =
encode_digest(calc_digest(decoded.as_slice(), counter, self.algorithm).as_ref())?;
let padded_code = format!(
"{:0width$}",
digest % 10_u32.pow(self.digits),
width = self.digits as usize
);
Ok(padded_code)
}
}
impl From<&TOTP> for HOTP {
fn from(totp: &TOTP) -> Self {
Self {
algorithm: totp.algorithm,
digits: totp.digits,
secret: totp.secret.clone(),
}
}
}