use hmac::{Hmac, Mac};
use sha1::Sha1;
type hmacsha1 = Hmac<Sha1>;
fn main() {
let key = "JBSWY3DPEHPK3PXP";
let step: u32 = 30;
let skew: u32 = 1;
let mut hmac = hmacsha1::new_from_slice(key.as_bytes()).unwrap();
let time = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs();
let time = time as u32 / step;
hmac.update(&time.to_be_bytes());
let mut result = hmac.finalize().into_bytes().to_vec();
let offset = result.last().unwrap() & 15;
let binary = (result[offset as usize] as u32 & 0x7f) << 24
| (result[(offset + 1) as usize] as u32 & 0xff) << 16
| (result[(offset + 2) as usize] as u32 & 0xff) << 8
| (result[(offset + 3) as usize] as u32 & 0xff);
let mut fin = binary % 10_u32.pow(6);
let fin_str = fin.to_string();
println!("{:?}", result.last());
println!("{:?}", fin_str);
}
当我为秘密运行此代码时,我没有得到预期的输出,我遵循了 totp 参考表并致力于他们在 java 中给出的实现,但它不起作用,有人可以看到我没有看到的东西吗
我期待正确的结果
通常,HOTP 或 TOTP 的密钥以 Base32 字符串形式给出,有时以十六进制或 Base64 字符串形式给出,尽管这些不太常见。但是,您实际上使用字符串作为密钥,而不是对其进行解码。
您可能想使用 base32 crate 将其解码为字节值。
此外,我可能建议您编写的代码在密钥和时间戳上更加通用,这将允许您在这里编写一些测试。很明显,它不会产生“正确的结果”,但如果您可以为已知值编写一些测试,那么就更容易知道您的代码是否确实做到了这一点。尤其如此,因为它涉及时间,而时间是一个移动的目标。