#totp #hmac #otp #2fa

totp-rs

以易用性为目标,并附加额外 QoL 功能的符合 RFC 的 TOTP 实现

23 个稳定版本 (4 个主要版本)

5.6.0 2024年7月24日
5.5.1 2024年1月19日
5.4.0 2023年10月4日
5.1.0 2023年7月15日
0.5.0 2020年7月3日

#22 in 身份验证

Download history 14649/week @ 2024-05-03 13156/week @ 2024-05-10 12909/week @ 2024-05-17 11351/week @ 2024-05-24 11778/week @ 2024-05-31 11089/week @ 2024-06-07 11172/week @ 2024-06-14 11039/week @ 2024-06-21 13275/week @ 2024-06-28 15543/week @ 2024-07-05 13510/week @ 2024-07-12 11090/week @ 2024-07-19 13212/week @ 2024-07-26 14126/week @ 2024-08-02 13992/week @ 2024-08-09 12397/week @ 2024-08-16

55,903 个月下载量
38 个 Crates (27 个直接使用) 中使用

MIT 许可证

87KB
1.5K SLoC

totp-rs

Build Status docs codecov cargo-audit

此库允许根据 TOTP 创建 2FA 身份验证令牌,验证这些令牌,并具有可配置的时间偏移量、每个令牌的有效时间、算法和数字位数!默认功能尽可能保持轻量级,以确保小型二进制文件和较短的编译时间。

它现在支持解析 otpauth URLs 到 totp 对象,并具有合理的默认值。

请注意,某些身份验证器应用程序将接受 SHA256SHA512 算法,但会静默回退到 SHA1,这将导致由于算法不匹配而导致 check() 函数失败。

功能


qr

使用可选功能 "qr",您可以使用它生成 base64 png 二维码。这将启用 otpauth 功能。

otpauth

使用可选功能 "otpauth",支持从 otpauth URL 解析 TOTP 参数,并生成 otpauth URL。它向 TOTP 添加了 2 个字段。

serde_support

使用可选功能 "serde_support",库定义的类型 TOTPAlgorithm 将支持反序列化和序列化。

gen_secret

使用可选功能 "gen_secret",将为您生成一个秘密以存储在数据库中。

zeroize

当 TOTP 结构被丢弃时,安全地将秘密信息归零。

steam

添加对 Steam TOTP 令牌的支持。

示例

摘要

  1. 理解秘密
  2. 生成令牌
  3. 启用二维码生成
  4. 启用 serde 支持
  5. 启用 otpauth url 支持
  6. 启用 gen_secret 支持
  7. 使用符合 RFC-6238 的默认值
  8. 从 steam 秘密生成新的 TOTP

理解秘密


此新类型被添加为区分原始和已 base32 编码的秘密。

Secret::Raw("TestSecretSuperSecret".as_bytes().to_vec())

等同于

Secret::Encoded("KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ".to_string())

生成令牌


将其添加到您的 Cargo.toml

[dependencies]
totp-rs = "^5.0"

然后您可以这样做

use std::time::SystemTime;
use totp_rs::{Algorithm, TOTP, Secret};

fn main() {
    let totp = TOTP::new(
        Algorithm::SHA1,
        6,
        1,
        30,
        Secret::Raw("TestSecretSuperSecret".as_bytes().to_vec()).to_bytes().unwrap(),
    ).unwrap();
    let token = totp.generate_current().unwrap();
    println!("{}", token);   
}

这相当于

use std::time::SystemTime;
use totp_rs::{Algorithm, TOTP, Secret};

fn main() {
    let totp = TOTP::new(
        Algorithm::SHA1,
        6,
        1,
        30,
        Secret::Encoded("KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ".to_string()).to_bytes().unwrap(),
    ).unwrap();
    let token = totp.generate_current().unwrap();
    println!("{}", token);   
}

带有二维码生成


将其添加到您的 Cargo.toml

[dependencies.totp-rs]
version = "^5.3"
features = ["qr"]

然后您可以这样做

use totp_rs::{Algorithm, TOTP, Secret};

fn main() {
    let totp = TOTP::new(
        Algorithm::SHA1,
        6,
        1,
        30,
        Secret::Encoded("KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ".to_string()).to_bytes().unwrap(),
        Some("Github".to_string()),
        "[email protected]".to_string(),
    ).unwrap();
    let qr_code = totp.get_qr_base64()?;
    println!("{}", qr_code);   
}

支持 serde


将其添加到您的 Cargo.toml

[dependencies.totp-rs]
version = "^5.0"
features = ["serde_support"]

支持 otpauth url


将其添加到您的 Cargo.toml

[dependencies.totp-rs]
version = "^5.0"
features = ["otpauth"]

然后您可以这样做

use totp_rs::TOTP;

fn main() {
    let otpauth = "otpauth://totp/GitHub:[email protected]?secret=KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ&issuer=GitHub";
    let totp = TOTP::from_url(otpauth).unwrap();
    println!("{}", totp.generate_current().unwrap());
}

支持 gen_secret


将其添加到您的 Cargo.toml

[dependencies.totp-rs]
version = "^5.3"
features = ["gen_secret"]

然后您可以这样做

use totp_rs::{Algorithm, TOTP, Secret};

fn main() {
    let totp = TOTP::new(
        Algorithm::SHA1,
        6,
        1,
        30,
        Secret::default().to_bytes().unwrap(),
        Some("Github".to_string()),
        "[email protected]".to_string(),
    ).unwrap();
    let qr_code = totp.get_qr_base64()?;
    println!("{}", qr_code);   
}

这相当于

use totp_rs::{Algorithm, TOTP, Secret};

fn main() {
    let totp = TOTP::new(
        Algorithm::SHA1,
        6,
        1,
        30,
        Secret::generate_secret().to_bytes().unwrap(),
        Some("Github".to_string()),
        "[email protected]".to_string(),
    ).unwrap();
    let qr_code = totp.get_qr_base64()?;
    println!("{}", qr_code);   
}

使用符合 RFC-6238 的默认值


您可以进行如下操作

use totp_rs::{Algorithm, TOTP, Secret, Rfc6238};

fn main () {
    let mut rfc = Rfc6238::with_defaults(
            Secret::Encoded("KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ".to_string()).to_bytes().unwrap(),
        )
        .unwrap();

    // optional, set digits
    rfc.digits(8).unwrap();

    // create a TOTP from rfc
    let totp = TOTP::from_rfc6238(rfc).unwrap();
    let code = totp.generate_current().unwrap();
    println!("code: {}", code);
}

使用 gen_secret 功能,您可以更进一步,并使所有值默认且安全。

注意:使用 otpauth 功能,TOTP.issuer 将为 None,而 TOTP.account_name 将为 """"。在生成 URL/QRCode 之前,请务必设置这些字段。

fn main() {
    let totp = TOTP::default();
    let code = totp.generate_current().unwrap();
    println!("code: {}", code);
}

从 steam 秘密生成新的 TOTP


将其添加到您的 Cargo.toml

[dependencies.totp-rs]
version = "^5.3"
features = ["steam"]

然后您可以这样做

use totp_rs::{TOTP, Secret};

fn main() {
    let totp = TOTP::new_steam(
        Secret::Encoded("KRSXG5CTMVRXEZLUKN2XAZLSKNSWG4TFOQ".to_string()).to_bytes().unwrap(),
    ).unwrap();
    let code = totp.generate_current().unwrap();
    println!("code: {}", code);   
}

依赖项

~0.5–1.7MB
~37K SLoC