lonewolf_auth_toolkit/mfa/
mod.rs1use std::time::{SystemTime, UNIX_EPOCH};
2
3use anyhow::Error;
4use rand::{thread_rng, Rng};
5use totp_rs::{Rfc6238, TOTP};
6
7pub fn generate_random_string() -> String {
16 let mut rng = thread_rng();
17 let random_bytes: [u8; 32] = rng.gen();
18 let hex_string: String = random_bytes.iter().map(|b| format!("{:02x}", b)).collect();
19
20 hex_string
21}
22
23pub async fn generate(issuer: String, account_name: String) -> Result<(String, String), Error> {
40 let secret_string = generate_random_string();
41 let mut rfc = Rfc6238::with_defaults(secret_string.clone().into_bytes().to_vec())?;
42
43 rfc.digits(6)?;
44 rfc.issuer(issuer);
45 rfc.account_name(account_name);
46
47 let totp = TOTP::from_rfc6238(rfc)?;
48 let qr_code = totp.get_qr_base64();
49
50 match qr_code {
51 Ok(qr_code) => Ok((qr_code, secret_string)),
52 Err(error) => Err(Error::msg(error)),
53 }
54}
55
56pub async fn verify(code: String, secret: String) -> Result<bool, Error> {
70 let mut rfc = Rfc6238::with_defaults(secret.clone().into_bytes().to_vec())?;
71
72 rfc.digits(6)?;
73
74 let totp = TOTP::from_rfc6238(rfc)?;
75 let time = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
76 let token = totp.generate(time);
77
78 Ok(code == token)
79}