Documentation
¶
Overview ¶
Package otp computes RFC 4226 HOTP and RFC 6238 TOTP one-time passwords. It is an offline post-exploitation primitive: when a 2FA seed has been recovered from captured loot (a secrets file, a config dump, an otpauth:// URI / QR payload), this derives the live codes — complementing the credential tooling (hash_identify, jwt_decode, kerberos_decode). It computes from an operator-supplied seed; it performs no network or device interaction.
Wrap-vs-native judgement ¶
Native. HOTP is HMAC + the RFC 4226 dynamic-truncation; TOTP is HOTP over a time-step counter. Both are a dozen lines on top of the standard library's crypto/hmac + crypto/sha*. There is nothing to wrap.
Verifiable / no confidently-wrong output ¶
This is the strongest verification class: RFC 4226 (Appendix D) and RFC 6238 (Appendix B) publish exact test vectors — seed "12345678901234567890", HOTP counter 0 -> 755224, TOTP SHA-1 T=59 -> 94287082, etc. The unit tests assert this package reproduces every published vector, so the algorithm ships only if it matches the authoritative reference.
Covered / deferred ¶
Covered: HOTP, TOTP, the SHA-1 / SHA-256 / SHA-512 HMAC variants, 6-8 digit codes, base32 seed decoding (the Google-Authenticator form), and the otpauth:// key-URI parser (ParseURI — the 2FA-enrolment QR artifact, carrying the algorithm / digits / period that drive the code), and Steam Guard (SteamGuard — RFC 6238 over SHA1/30s mapped to Steam's 5-character alphabet, from a base64 shared_secret). Nothing in this package is deferred.
Index ¶
- func DecodeSecret(s string) ([]byte, error)
- func DecodeSecretBase64(s string) ([]byte, error)
- func HOTP(key []byte, counter uint64, digits int, h func() hash.Hash) string
- func HashFor(algo string) (func() hash.Hash, error)
- func SteamGuard(key []byte, t time.Time) string
- func TOTP(key []byte, t time.Time, period, digits int, h func() hash.Hash) string
- type URIParams
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DecodeSecret ¶
DecodeSecret decodes a base32 2FA secret, tolerating spaces, lowercase, and missing '=' padding (the common Google-Authenticator form).
func DecodeSecretBase64 ¶ added in v0.443.0
DecodeSecretBase64 decodes a base64 2FA secret — the form Steam stores its shared_secret in (the maFile / loot form), as opposed to the base32 Google- Authenticator form. Standard and raw (unpadded) base64 are both accepted.
func SteamGuard ¶ added in v0.443.0
SteamGuard computes a Steam Guard mobile-authenticator code for time t. Steam uses RFC 6238 over an HMAC-SHA1 / 30-second step (T0 = 0) but, instead of the decimal modulo, maps the 31-bit truncated value to a fixed 5-character alphabet: take value mod 26 as an index five times, dividing by 26 each step. The seed is Steam's base64 shared_secret (decode with DecodeSecretBase64).
Types ¶
type URIParams ¶ added in v0.442.0
type URIParams struct {
Type string // "totp" or "hotp"
Secret string // base32 secret (decode with DecodeSecret)
Algorithm string // SHA1 / SHA256 / SHA512 (default SHA1)
Digits int // 6-8 (default 6)
Period int // TOTP step seconds (default 30)
Counter uint64 // HOTP counter (valid only when HasCounter)
HasCounter bool
Issuer string
Account string
}
URIParams holds the fields parsed from a Google-Authenticator otpauth:// key URI — the form encoded in a 2FA-enrolment QR code and emitted by authenticator exports. The secret is returned base32 (as it appears in the URI); decode it with DecodeSecret.
func ParseURI ¶ added in v0.442.0
ParseURI parses an otpauth:// key URI per Google's Key-URI-Format
otpauth://TYPE/[ISSUER:]ACCOUNT?secret=BASE32&issuer=…&algorithm=…&digits=…&period=…&counter=…
into its fields, applying the spec defaults (algorithm SHA1, digits 6, period 30) for absent parameters. It exists so totp_generate can consume the real 2FA artifact directly: the URI carries the algorithm / digits / period that drive the code, so feeding the raw base32 secret alone (and relying on the SHA1/6/30 defaults) would silently produce wrong codes whenever the enrolment used, say, SHA256 or 8 digits. The label's ISSUER:ACCOUNT is parsed for display; an explicit issuer= query parameter wins over the label prefix.