OTP Package

A comprehensive Go library for generating and validating Time-based One-Time Passwords (TOTP) and HMAC-based One-Time Passwords (HOTP).

Go 1.16+ RFC 6238 RFC 4226 Thread-Safe

Overview

The OTP package provides a complete implementation of Time-based One-Time Password (TOTP) and HMAC-based One-Time Password (HOTP) algorithms according to RFC 6238 and RFC 4226 specifications.

TOTP Support

Generate and validate time-based OTP codes with configurable time periods and validation windows.

HOTP Support

Counter-based OTP generation with flexible counter management and validation.

Multiple Hash Algorithms

Support for SHA-1, SHA-256, and SHA-512 hashing algorithms.

QR Code Integration

Generate QR codes and otpauth URLs for authenticator app integration.

Backup Codes

Generate and validate backup recovery codes for account recovery.

Thread-Safe

All operations are thread-safe and can be used in concurrent environments.

Installation

Install the OTP package using Go modules:

Go Get

go get github.com/MateoCaicedoW/otp

Then import it in your Go code:

import "github.com/MateoCaicedoW/otp"

Quick Start

Basic TOTP Example

package main
import (
    "fmt"
    "log"
    "github.com/MateoCaicedoW/otp"
)

func main() {
    // Generate a new secret
    secret, err := otp.GenerateSecret(32)
    if err != nil {
        log.Fatal(err)
    }

    // Create TOTP configuration
    config := otp.NewTOTP(secret, "MyApp", "user@example.com", 6, 30)

    // Generate current TOTP
    code, err := config.GenerateTOTP()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Current TOTP: %s\n", code)

    // Validate the code
    valid, err := config.ValidateTOTP(code, 1)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Code is valid: %v\n", valid)
}
                    

Basic HOTP Example

// Create HOTP configuration
config := otp.NewHOTP(secret, "MyApp", "user@example.com", 6, 0)

// Generate HOTP
code, err := config.GenerateHOTP()
if err != nil {
    log.Fatal(err)
}

// Validate and get next counter
valid, nextCounter, err := config.ValidateHOTP(code, 10)
if valid {
    config.SetCounter(nextCounter + 1)
}

Configuration

Config Struct

The Config struct holds all configuration parameters for OTP generation:

type Config struct {
    // Secret is the shared secret key (base32 encoded)
    Secret string
    
    // Digits is the number of digits in the OTP (default: 6)
    Digits int
    
    // Algorithm is the hashing algorithm (default: SHA1)
    Algorithm Algorithm
    
    // Period is the time period in seconds for TOTP (default: 30)
    Period int
    
    // Counter is the counter value for HOTP
    Counter uint64
    
    // Issuer is the name of the service issuing the OTP
    Issuer string
    
    // AccountName is the name of the account
    AccountName string
}

Algorithms

The package supports three hashing algorithms:

Algorithm Constant Description
SHA-1 AlgorithmSHA1 Default algorithm, widely supported
SHA-256 AlgorithmSHA256 More secure alternative to SHA-1
SHA-512 AlgorithmSHA512 Highest security option

Default Configuration

Create a configuration with default values:

config := otp.DefaultConfig()
config.Secret = "your-secret-here"
config.Issuer = "MyApp"
config.AccountName = "user@example.com"

TOTP (Time-based OTP)

Generation

Generate TOTP codes for the current time or specific timestamps:

// Generate for current time
code, err := config.GenerateTOTP()

// Generate for specific time
specificTime := time.Now().Add(-30 * time.Second)
code, err := config.GenerateTOTPAt(specificTime)

// Generate batch for multiple time windows
entries, err := config.GenerateTOTPBatch(5)

Validation

Validate TOTP codes with configurable time windows:

// Validate with default window (±1 period)
valid, err := config.ValidateTOTP(code, 1)

// Validate at specific time
valid, err := config.ValidateTOTPAt(code, time.Now(), 2)
Note: The window size determines how many time periods before and after the current time are considered valid. A window size of 1 allows codes from the previous, current, and next time periods.

Utilities

Additional TOTP utility functions:

// Get remaining time until current code expires
remaining := config.GetRemainingTime()

// Get next TOTP generation time
nextTime := config.GetNextTOTPTime()

// Get current time window boundaries
start, end := config.GetCurrentTOTPWindow()

HOTP (HMAC-based OTP)

Generation

Generate HOTP codes using counter values:

// Generate using current counter
code, err := config.GenerateHOTP()

// Generate for specific counter
code, err := config.GenerateHOTPAt(123)

Validation

Validate HOTP codes within a counter window:

// Validate with counter window
valid, nextCounter, err := config.ValidateHOTP(code, 10)
if valid {
    // Update counter to prevent reuse
    config.SetCounter(nextCounter + 1)
}
Important: Always update the counter after successful validation to prevent replay attacks.

Counter Management

Manage HOTP counter values:

// Set counter to specific value
config.SetCounter(100)

// Increment counter and get new value
newCounter := config.IncrementCounter()

// Get current counter value
currentCounter := config.Counter

Security Features

Secret Generation

Generate cryptographically secure random secrets:

// Generate 32-byte secret (recommended)
secret, err := otp.GenerateSecret(32)

// Generate with custom length
secret, err := otp.GenerateSecret(64)

// Validate existing secret
err := otp.ValidateSecret(secret)

Backup Codes

Generate and validate backup recovery codes:

// Generate backup codes
codes, err := otp.GenerateBackupCodes(10)

// Validate backup code
valid := otp.ValidateBackupCode(userInput, storedCode)

QR Codes

Generate QR codes and otpauth URLs for authenticator apps:

// Get QR code URL
qrURL, err := config.GetQRCodeURL()

// Get otpauth URL
otpauthURL, err := config.GetOTPAuthURL()

// Parse otpauth URL
parsedConfig, err := otp.ParseOTPAuthURL(otpauthURL)

API Reference

Methods

Method Description Returns
GenerateSecret(length int) Generate a cryptographically secure random secret string, error
ValidateSecret(secret string) Validate a base32-encoded secret error
GenerateTOTP() Generate TOTP for current time string, error
GenerateTOTPAt(t time.Time) Generate TOTP for specific time string, error
ValidateTOTP(code string, windowSize int) Validate TOTP with time window bool, error
ValidateTOTPAt(code string, t time.Time, windowSize int) Validate TOTP at specific time bool, error
GenerateHOTP() Generate HOTP using current counter string, error
GenerateHOTPAt(counter uint64) Generate HOTP for specific counter string, error
ValidateHOTP(code string, windowSize int) Validate HOTP with counter window bool, uint64, error
GetQRCodeURL() Generate QR code URL for authenticator apps string, error
GetOTPAuthURL() Generate otpauth URL string, error
GenerateBackupCodes(count int) Generate backup recovery codes []string, error
ValidateBackupCode(provided, stored string) Validate backup code with constant-time comparison bool

Types

type Algorithm int

const (
    AlgorithmSHA1 Algorithm = iota
    AlgorithmSHA256
    AlgorithmSHA512
)

type Config struct {
    Secret      string
    Digits      int
    Algorithm   Algorithm
    Period      int
    Counter     uint64
    Issuer      string
    AccountName string
}

type TOTPEntry struct {
    Code      string
    ValidFrom time.Time
    ValidTo   time.Time
    IsCurrent bool
}

Error Handling

The package returns descriptive errors for various failure conditions:

// Common error scenarios
if err != nil {
switch {
    case strings.Contains(err.Error(), "invalid base32 secret"):
        // Handle invalid secret format
    case strings.Contains(err.Error(), "digits must be between 1 and 10"):
        // Handle invalid digits configuration
    case strings.Contains(err.Error(), "secret is required"):
        // Handle missing secret
    case strings.Contains(err.Error(), "account name is required"):
        // Handle missing account name
    default:
        // Handle other errors
    }
}