Files
mcias/data/totp.go
Kyle Isom c8a6830a80 Restart.
Data foundation started, with updated guidelines and
golangci-lint config.
2025-11-16 19:22:26 -08:00

48 lines
1.1 KiB
Go

package data
import (
"strings"
"time"
twofactor "git.wntrmute.dev/kyle/goutils/twofactor"
)
const totpPeriod = 30
// builtinTOTPValidator delegates TOTP validation to goutils/twofactor.
type builtinTOTPValidator struct{}
func (builtinTOTPValidator) Validate(secret, code string, at time.Time, window int) bool {
if secret == "" || code == "" {
return false
}
// Normalize secret similar to common authenticator apps: remove spaces and uppercase.
norm := strings.ToUpper(strings.ReplaceAll(secret, " ", ""))
norm = twofactor.Pad(norm)
otp, err := twofactor.NewGoogleTOTP(norm)
if err != nil || otp == nil {
return false
}
// Compute the base counter for the provided time (period 30s, start 0).
base := uint64(at.Unix()&unsignedMask64) / totpPeriod // #nosec G115 - masked off overflow
// Check +/- window steps.
for i := -window; i <= window; i++ {
var ctr uint64
if i < 0 {
// Guard underflow.
offs := uint64(-i)
if offs > base {
continue
}
ctr = base - offs
} else {
ctr = base + uint64(i)
}
if otp.OATH.OTP(ctr) == code {
return true
}
}
return false
}