# totpyx
A tiny, dependency-free TOTP generator (RFC 6238) with a strict RFC 4648 Base32 decoder.
This project exists for a single purpose: to provide a fully auditable TOTP implementation with no third-party crypto dependencies, no hidden behavior, and a deliberately minimal attack and trust surface.
## What it is
- **TOTP (RFC 6238)** generator
- **HMAC algorithms:** SHA-1, SHA-256, SHA-512
- **Digits:** 6, 7, or 8
- **Period (X):** configurable (default 30 seconds)
- **T0:** configurable (default 0)
- **Time override:** supply an explicit Unix timestamp to reproduce test vectors or debug clock drift
- **Base32 decoding:** RFC 4648 alphabet (`A–Z2–7`), case-insensitive, optional `=` padding
## What it is not
- Not a password manager
- Not a QR or provisioning URI parser
- Not secret storage
- Not a general-purpose cryptography library
- Not a formally audited security product
This crate computes TOTP codes. Secret storage, lifecycle, and protection are intentionally left to the caller.
## Install
As a CLI:
```bash
cargo install totpyx
```
As a library:
```bash
cargo add totpyx
```
## CLI usage
```bash
totpyx <base32-secret> \
[--algo sha1|sha256|sha512] \
[--digits 6|7|8] \
[--period <seconds>] \
[--t0 <unix>] \
[--time <unix>]
```
### Examples
Generate a standard 6-digit TOTP (SHA-1, 30s period, T0=0):
```bash
totpyx JBSWY3DPEHPK3PXP
```
Generate SHA-256 with 8 digits:
```bash
totpyx JBSWY3DPEHPK3PXP --algo sha256 --digits 8
```
Generate with a custom period:
```bash
totpyx JBSWY3DPEHPK3PXP --period 60
```
Reproduce a code for a specific Unix timestamp (debugging drift, server-side validation):
```bash
totpyx JBSWY3DPEHPK3PXP --time 1710000000
```
### Notes on secrets
- If your issuer provides a Base32 secret with spaces or hyphens, remove them first.
- Padding `=` at the end is allowed but not required.
- Invalid lengths or padding are rejected intentionally.
## Library usage
Minimal example:
```rust
use totpyx::crypto::HashAlgo;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let secret = totpyx::base32::decode("JBSWY3DPEHPK3PXP")?;
let unix_time = 1_710_000_000u64;
let code = totpyx::totp::generate_totp(
&secret,
unix_time,
30, // period (X)
0, // T0
6, // digits
HashAlgo::Sha1,
)?;
println!("{code}");
Ok(())
}
```
## Spec compliance
- TOTP is computed as HOTP(K, T) where `T = (unix_time - T0) / X` (RFC 6238 §4).
- Dynamic truncation follows the HOTP truncation method, including MSB masking to avoid signed/unsigned ambiguity (RFC 4226 §5.3).
- Output digits are restricted to 6, 7, or 8 (RFC 4226 §5.4).
- HMAC modes SHA-1, SHA-256, and SHA-512 are implemented and validated against the RFC 6238 Appendix B test vectors.
- Base32 decoding follows RFC 4648 strictly, including alphabet, padding rules, and invalid length handling.
## References
This create implements the relevant standards directly, without abstraction or reinterpretation. The primary references are:
- **RFC 6238 — Time-Based One-Time Password Algorithm (TOTP)**
[https://www.rfc-editor.org/rfc/rfc6238](https://www.rfc-editor.org/rfc/rfc6238)
- **RFC 4226 — HMAC-Based One-Time Password Algorithm (HOTP)**
[https://www.rfc-editor.org/rfc/rfc4226](https://www.rfc-editor.org/rfc/rfc4226)
- **RFC 2104 — HMAC: Keyed-Hashing for Message Authentication**
[https://www.rfc-editor.org/rfc/rfc2104](https://www.rfc-editor.org/rfc/rfc2104)
- **FIPS 180-4 — Secure Hash Standard (SHS)**
[https://csrc.nist.gov/publications/detail/fips/180/4/final](https://csrc.nist.gov/publications/detail/fips/180/4/final)
- **RFC 4648 — The Base16, Base32, and Base64 Data Encodings**
[https://www.rfc-editor.org/rfc/rfc4648](https://www.rfc-editor.org/rfc/rfc4648)
All test vectors included in this repository are taken directly from the referenced specifications.
## License
Apache-2.0 © [@rccyx](https://rccyx.com)