totp-rs

RFC 6238-compliant TOTP two-factor authentication for Rust

Library
Cargo
v6.0.0
271stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
77/100Good
Development Activity92
Maintenance84
Community52
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
74/100Good
Architecture74
Code Quality78
Innovation65
Learning Curve78

totp-rs implements Time-based One-Time Password (TOTP) generation and verification per RFC 6238, aimed at making 2FA easy to add to Rust applications without sacrificing correctness. It supports SHA1/SHA256/SHA512 algorithms, configurable digit counts, time-step and clock-skew tolerance, and can build a TOTP either from raw parameters or by parsing a Google Authenticator-style otpauth:// URL.

Optional Cargo features round out the common 2FA workflows: qr generates a base64-encoded QR code image for onboarding, serde_support makes TOTP/Algorithm (de)serializable, gen_secret generates cryptographically random secrets, zeroize securely wipes secret material on drop, and steam adds support for Steam’s non-standard TOTP variant.

What You Get

  • TOTP::new() and TOTP::from_rfc6238() constructors covering both custom and RFC-6238-default configurations
  • generate_current() / check() for producing and validating time-based codes with configurable clock skew
  • otpauth feature for parsing and generating Google-Authenticator-style otpauth:// URLs
  • qr feature for generating a base64 PNG QR code directly from a TOTP instance
  • gen_secret, serde_support, zeroize, and steam features for secret generation, serialization, secure memory wiping, and Steam-variant TOTP support

Common Use Cases

  • Adding TOTP-based 2FA login flows to a Rust web backend, generating QR codes for authenticator-app enrollment
  • Verifying user-submitted 6-digit codes against a stored secret during authentication
  • Building password-manager or authenticator-style tools that need to parse otpauth:// URLs exported from other apps
  • Generating and securely storing per-user TOTP secrets with the gen_secret and zeroize features

Under The Hood

Architecture — The crate centers on a TOTP struct (src/lib.rs, the bulk of the ~2,400-line codebase) holding algorithm, digits, skew, step, and secret, with generate_current()/generate()/check()/check_current() methods computing HMAC-based codes per RFC 6238. src/secret.rs defines a Secret enum (Raw vs Encoded) that disambiguates base32-encoded from raw-byte secrets before conversion to bytes. src/rfc.rs implements an Rfc6238 builder for RFC-compliant defaults, and src/url_error.rs / the otpauth feature path in lib.rs handle parsing and generating otpauth:// URLs, with src/custom_providers.rs adding provider-specific quirks (e.g. Steam’s TOTP variant).

Tech Stack — Rust 2021 edition (MSRV 1.66), built on sha1/sha2 for the HMAC algorithms, hmac and constant_time_eq for constant-time code comparison, base32 for secret encoding, with optional url/urlencoding (otpauth), qrcodegen-image (qr), serde (serde_support), rand (gen_secret), and zeroize (zeroize) behind feature flags to keep the default build minimal.

Code Quality — The project runs a dedicated security.yml GitHub Actions workflow (cargo-audit) alongside its main Rust CI and reports coverage via Codecov, and the crate explicitly documents a known gotcha (some authenticator apps silently fall back to SHA1 even when SHA256/SHA512 is configured, causing check() mismatches) rather than papering over it. Sensitive comparisons use constant_time_eq to avoid timing side-channels, and the zeroize feature is opt-in specifically for secret-handling hygiene — both signal security-conscious design for a crate handling authentication secrets.

API Design — Core usage is a single TOTP::new(...) call followed by generate_current(), with RFC-default and URL-based construction available as alternate entry points (from_rfc6238, from_url) for different starting points. Cargo features add capability without bloating the default dependency set, though users must remember which feature flag unlocks which method (e.g. otpauth for from_url, qr for get_qr_base64) — a small discoverability cost documented clearly in the README’s example-by-feature structure.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search