otp

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jun 3, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

README

otp

Go code to generate one-time passwords based on RFCs 4226 and 6238.

Documentation

Overview

Package otp provides tools for generating and validating one-time passwords (OTPs) according to the HOTP (RFC 4226) and TOTP (RFC 6238) standards.

Index

Examples

Constants

View Source
const DefaultTimeStepSeconds int64 = 30

DefaultTimeStepSeconds defines the time step in seconds used to calculate the TOTP counter, as per RFC 6238.

Variables

This section is empty.

Functions

func ConstantTimeEqual added in v0.2.0

func ConstantTimeEqual(x, y string) bool

ConstantTimeEqual compares two OTP strings to prevent timing attacks.

func DecodeSecret added in v0.2.0

func DecodeSecret(s string) ([]byte, error)

DecodeSecret decodes a base32-encoded secret string into raw bytes. Input is accepted in upper or lower case and without padding characters.

func EncodeSecret added in v0.2.0

func EncodeSecret(secret []byte) string

EncodeSecret encodes secret as a base32 string without padding, suitable for provisioning URIs and QR codes.

func FormatURI added in v0.2.0

func FormatURI(u URI) (string, error)

FormatURI encodes a URI as an otpauth:// string. Default values (SHA1, 6 digits, 30-second period) are omitted from the output. URI.Secret is base32-encoded without padding.

func GenerateHOTP

func GenerateHOTP(secret []byte, counter uint64, digits uint) (string, error)

GenerateHOTP generates a HMAC-based One-Time Password (HOTP) per RFC 4226 using the provided secret, counter, and the desired OTP length in digits.

Example
secret := []byte("12345678901234567890")
counter := uint64(9)
digits := uint(6)

hotp, err := GenerateHOTP(secret, counter, digits)
if err != nil {
	fmt.Println("Error generating HOTP:", err)
	return
}

fmt.Printf("secret: 0x%x\n", secret)
fmt.Printf("counter: %d\n", counter)
fmt.Printf("digits: %d\n", digits)
fmt.Printf("HOTP: %s\n", hotp)
Output:
secret: 0x3132333435363738393031323334353637383930
counter: 9
digits: 6
HOTP: 520489

func GenerateSecret added in v0.2.0

func GenerateSecret(n uint) ([]byte, error)

GenerateSecret returns a cryptographically random secret of n bytes, suitable for use with GenerateTOTP or GenerateHOTP.

RFC 4226 requires a minimum of 16 bytes (128 bits) and recommends at least 20 bytes (160 bits).

func GenerateTOTP

func GenerateTOTP(secret []byte, timestamp time.Time, opts TOTPOptions) (string, error)

GenerateTOTP generates a Time-based One-Time Password (TOTP) per RFC 6238 using the provided secret, timestamp, and the desired OTP length in digits. It allows for a custom hash function; if none is provided, SHA-1 is used by default.

Example
secret := []byte("12345678901234567890")
layout := "2006-01-02 15:04:05"
parsedTime, err := time.Parse(layout, "2033-05-18 03:33:20")
if err != nil {
	fmt.Println(err)
	return
}
digits := uint(8)

fmt.Println("secret", secret)
fmt.Println("time", parsedTime)
fmt.Println("digits", digits)

totp, err := GenerateTOTP(secret, parsedTime, TOTPOptions{Digits: 8})
if err != nil {
	fmt.Println("Error generating TOTP:", err)
	return
}

fmt.Println("TOTP:", totp)
Output:
secret [49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48]
time 2033-05-18 03:33:20 +0000 UTC
digits 8
TOTP: 69279037

func ValidateHOTP added in v0.2.0

func ValidateHOTP(secret []byte, code string, counter uint64, lookAhead uint,
	digits uint) (bool, uint64, error)

ValidateHOTP checks whether code matches the HOTP for secret at any counter step in [counter, counter+lookAhead]. It returns the next counter value the caller should store for replay prevention. A lookAhead of 0 requires an exact match; RFC 4226 recommends a default window of 10.

func ValidateTOTP added in v0.2.0

func ValidateTOTP(secret []byte, code string, timestamp time.Time, skew uint, opts TOTPOptions) (matched bool, counter uint64, err error)

ValidateTOTP checks whether code matches the TOTP for secret at timestamp, allowing skew steps in either direction for clock drift tolerance. It returns the matched counter step so callers can store it for replay prevention. A skew of 1 allows the previous and next 30-second windows (RFC 6238 recommendation).

Types

type HashFunc added in v0.2.0

type HashFunc func() hash.Hash

HashFunc is a function that returns a new hash.Hash, used to specify the hashing algorithm for OTP generation.

type TOTPOptions added in v0.2.0

type TOTPOptions struct {
	Digits   uint
	HashFunc HashFunc
	TimeStep int64
}

type URI added in v0.2.0

type URI struct {
	Type      string // "totp" or "hotp"
	Issuer    string
	Account   string
	Secret    []byte // raw bytes (decoded from base32)
	Algorithm string // "SHA1", "SHA256", or "SHA512"; empty defaults to SHA1
	Digits    uint   // 0 defaults to 6
	Period    int64  // TOTP: seconds per window; 0 defaults to 30
	Counter   uint64 // HOTP: initial counter value
}

URI represents a parsed otpauth:// URI as defined by the Google Authenticator Key URI Format specification.

func ParseURI added in v0.2.0

func ParseURI(rawURI string) (URI, error)

ParseURI parses an otpauth:// URI and returns a URI. The secret query parameter is base32-decoded into URI.Secret. Period (TOTP) and Counter (HOTP) are always set, using spec defaults when the parameter is absent. Algorithm is normalized to uppercase.

func (URI) HashFunc added in v0.2.0

func (u URI) HashFunc() (HashFunc, error)

HashFunc returns the hash constructor for the URI's Algorithm field.

func (URI) TOTPOptions added in v0.2.0

func (u URI) TOTPOptions() (TOTPOptions, error)

TOTPOptions converts the URI into a TOTPOptions value ready for use with GenerateTOTP or ValidateTOTP. Zero-value fields use their spec defaults (SHA1, 6 digits, 30-second period) via TOTPOptions.withDefaults.

Directories

Path Synopsis
cmd
gentotp command
rfcdemo command
totp command

Jump to

Keyboard shortcuts

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