totp

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 10, 2026 License: AGPL-3.0 Imports: 14 Imported by: 0

Documentation

Overview

Package totp implements RFC 6238 TOTP (time-based one-time password) enrollment and verification. We use SHA-1 / 30-second period / 6 digits to maximize authenticator-app compatibility (every popular app speaks these defaults; SHA-256/512 cause real-world surprises).

Counter anti-replay is enforced at the DB layer (BumpTOTPCounter only advances last_used_counter when the new step is strictly greater).

Index

Constants

View Source
const Digits = otp.DigitsSix

Digits is the number of digits in the generated code.

View Source
const Period uint = 30

Period is the time-step in seconds.

View Source
const QRSize = 256

QRSize is the rendered SVG side length in CSS pixels (the SVG itself is resolution-independent; this drives the viewport-mapped size).

View Source
const RecoveryCodeCount = 10

RecoveryCodeCount is the number of recovery codes generated per user.

View Source
const RecoveryCodeGroupSize = 4

RecoveryCodeGroupSize is the length of each group.

View Source
const RecoveryCodeGroups = 3

RecoveryCodeGroups is the number of dash-separated groups in the rendered code (currently 3, of 4 chars each → 12 chars total).

View Source
const SecretSize = 20

SecretSize is the secret length in bytes. 20 is the RFC 4226/6238 recommendation (160 bits — comfortably above brute-force reach).

View Source
const SkewSteps uint = 1

SkewSteps is the number of windows ±0 we accept either side of `now`. A value of 1 means accept now-30s, now, now+30s — covers normal clock drift without expanding the replay window meaningfully.

Variables

View Source
var ErrInvalid = errors.New("totp: invalid code")

ErrInvalid means the code doesn't match (or doesn't look like one). Distinct from a generation error so callers can branch on it.

View Source
var ErrRecoveryCodeInvalid = errors.New("totp: recovery code invalid")

ErrRecoveryCodeInvalid is returned by callers when the typed code doesn't match any stored hash.

Functions

func EncodeBase32

func EncodeBase32(secret []byte) string

EncodeBase32 returns the Base32 encoding (no padding) authenticator apps display to the user. Used in the otpauth URI.

func EqualHash

func EqualHash(a, b []byte) bool

EqualHash compares two recovery-code hashes in constant time. Used by callers that read a candidate hash from the DB and want to compare to a value they computed themselves.

func Generate

func Generate(secret []byte, t time.Time) (string, error)

Generate returns the current 6-digit code for secret. Test affordance — not used at runtime by the server, only in tests.

func GenerateRecoveryCodes

func GenerateRecoveryCodes() ([]string, [][]byte, error)

GenerateRecoveryCodes mints RecoveryCodeCount fresh codes. Returns the human-readable strings (XXXX-XXXX-XXXX) that are shown to the user once, and the matching sha256 hashes (stored in the DB).

func GenerateSecret

func GenerateSecret() ([]byte, error)

GenerateSecret returns a fresh 20-byte secret.

func HashRecoveryCode

func HashRecoveryCode(code string) []byte

HashRecoveryCode returns the sha256 hash of the normalized form of code, suitable for DB lookup.

func LooksLikeRecoveryCode

func LooksLikeRecoveryCode(s string) bool

LooksLikeRecoveryCode is a cheap predicate the login challenge handler uses to distinguish a recovery code from a TOTP code: alphanumeric and of the expected post-normalization length.

func NormalizeRecoveryCode

func NormalizeRecoveryCode(s string) string

NormalizeRecoveryCode strips dashes/whitespace and uppercases the result so codes typed with stray spaces or lowercase still match.

func OtpauthURI

func OtpauthURI(issuer, accountName string, secret []byte) string

OtpauthURI builds the canonical otpauth:// URI consumed by authenticator apps. issuer is the site name (e.g. "shithub"); accountName is the user's canonical identifier (we use "shithub:<username>"). The URI carries the secret in plaintext — never log it; redactor scrubs it as defense in depth.

func QRSVG

func QRSVG(otpauthURI string) (template.HTML, error)

QRSVG renders the otpauth URI as an SVG QR code suitable for inline embedding in a template. Returns template.HTML so html/template doesn't double-escape the markup.

The URI is high-entropy and contains the secret. Callers MUST NOT log either the URI or the rendered SVG.

func Step

func Step(t time.Time) int64

Step returns the RFC 6238 step counter for time t.

func Verify

func Verify(secret []byte, code string, t time.Time) (int64, error)

Verify checks code against secret with ±SkewSteps tolerance. On acceptance, returns the step counter that matched so the caller can reject codes whose counter is <= last_used_counter.

Returns (step, nil) on accepted code; (0, err) otherwise. err is distinguishable via ErrInvalid for bad codes (vs. real errors).

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL