2个版本

0.1.11 2022年10月3日
0.1.1 2022年10月2日
0.1.0 2022年10月2日

#1136 in 密码学


用于 hextacy

MIT 许可证

45KB
519

基于时间和Hmac的一次性密码

基于RFC 4226的Hmac-based OTPs和基于RFC 6238的Time-based OTPs的OTP实现。

默认启用所有功能,如果您只想使用默认功能(没有encodingcustomqr模块),请使用标志default-features = false

此模块本身允许您使用默认算法SHA-1、默认数字长度6和默认时间步长30生成和验证TOTPs和HOTPs。

以下内容仅适用于您设置了default-features = false的情况,默认情况下它们是包含的:

如果您需要更精细地控制密码生成和验证,请使用custom_otp功能标志来访问自定义模块。

encoding功能标志提供了对编码模块的访问,该模块提供了将生成的密钥编码和解码为所选编码的2个基本功能,这些编码来自data_encoding crate。

qr功能标志提供了对qr模块的访问,并启用生成用于认证应用使用的生成的密钥的QR码。

示例用法

use thotp::{
    otp,
    verify_totp,
    generate_secret,
    encoding::{encode, decode},
    qr::generate_code,
};
use std::time::{SystemTime, UNIX_EPOCH};

// The default time step used by this module internally
const TIME_STEP: u8 = 30;

// Generate an encoded secret

let secret = generate_secret(80);

// The data_encoding crate is re-exported for convenience
let encoded = encode(&secret, data_encoding::BASE32);
 
// Store the secret somewhere safe

let qr_code = generate_code(
    // Type of otp
    "totp",
    // The encoded secret
    &encoded,
    // Your big corp title
    "Big Corp:[email protected]",
    // Your big corp issuer
    "Big Corp",
    // The qr code width (None defaults to 200)
    None,
    // The qr code height (None defaults to 200)
    None,
    // Correction level, M is the default
    qrcode::EcLevel::M
)
.expect("uh oh");

// Scan qr with some authenticator app

// Verify a password provided from the client, assume this is what they calculated

// When generating an OTP we have to calculate the current time slice
let time_step_now = SystemTime::now()
     .duration_since(UNIX_EPOCH)
     .unwrap()
     .as_secs()
     / TIME_STEP as u64;

let pw = otp(&secret, time_step_now).unwrap();

// The verify function does this internally
let (result, discrepancy) = verify_totp(&pw, &secret, 0).unwrap();

assert_eq!((true, 0),(result, discrepancy));

此模块内部使用了3个常量;

DIGITS_DEFAULT常量是otp函数生成的默认密码长度,以及验证时使用的长度,等于6。

TIME_STEP是默认和RFC推荐的时间步长,用于将现在到Unix纪元的时间长度以秒为单位分割,等于30。

当生成TOTP时,有可能它们会在时间步的末尾生成,等到它们到达服务器时,密码可能已经无效,因为它们会落在上一个时间步中。这种情况可以通过允许来自当前时间步前后ALLOWED_DRIFT个时间步的密码有效来缓解。这个值是RFC推荐的数量1,意味着当前时间步前后的时间片的密码被认为是有效的。

同样的漂移也可能发生在带有计数器的HOTP中,可以使用前瞻参数来调整从当前计数器将考虑多少密码有效。

依赖关系

~1–3MB
~38K SLoC