Documentation
¶
Overview ¶
Package totp implements RFC 6238 time-based one-time passwords over the RFC 4226 HOTP construction, for the dashboard's 2FA (PRD §10.2, §23.3).
It is written in-house rather than imported: the whole algorithm is one HMAC, a truncation and a modulo — pinned to the RFC test vectors below — and a dependency would be more code to audit than this file.
The parameters are the de-facto interoperable set (SHA-1, 6 digits, 30 s steps): every authenticator app supports them, and several support nothing else. SHA-1's collision weakness is irrelevant here — HMAC-SHA1 is not collision-bound, and the secret is 160 bits of entropy.
Index ¶
Constants ¶
const ( // Digits in a code. Six is what authenticator apps display by default. Digits = 6 // Period is the length of one time step. Period = 30 * time.Second // SecretSize is the secret length in bytes: 160 bits, the RFC 4226 // recommended minimum, and exactly one SHA-1 block of entropy. SecretSize = 20 // Skew is how many steps on EACH side of "now" a code is accepted for. // One step absorbs clock drift and the human delay between reading a code // and submitting it; more would multiply an attacker's guessing budget. Skew = 1 )
Variables ¶
This section is empty.
Functions ¶
func GenerateSecret ¶
GenerateSecret returns a fresh random secret in its base32 form.
func URI ¶
URI renders the otpauth:// provisioning URI for a secret, as authenticator apps consume it (via QR code or tap). The label is "issuer:account" and the issuer is repeated as a parameter — both are required for apps to file the entry under the right name.
func Validate ¶
Validate checks a code against the secret at the given instant, accepting ±Skew steps of drift. It returns the step the code matched, so the caller can persist it and refuse the SAME step next time — a TOTP is one-time only if somebody remembers it was used (data-dictionary §4.3 last_used_at).
The comparison is constant-time per candidate step. The scan deliberately tries every candidate even after a match: whether a code matched the first or the last step must not be measurable.
Types ¶
This section is empty.