working TOTP codes YIPPEE

This commit is contained in:
ari melody 2025-01-21 00:30:43 +00:00
parent 7044f7344b
commit 39b332b477
Signed by: ari
GPG key ID: CF99829C92678188
2 changed files with 23 additions and 2 deletions

View file

@ -3,26 +3,35 @@ package controller
import ( import (
"arimelody-web/model" "arimelody-web/model"
"crypto/hmac" "crypto/hmac"
"crypto/rand"
"crypto/sha1" "crypto/sha1"
"encoding/base32"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"math" "math"
"net/url" "net/url"
"os"
"strings" "strings"
"time" "time"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
) )
const TOTP_SECRET_LENGTH = 32
const TIME_STEP int64 = 30 const TIME_STEP int64 = 30
const CODE_LENGTH = 6 const CODE_LENGTH = 6
func GenerateTOTP(secret string, timeStepOffset int) string { func GenerateTOTP(secret string, timeStepOffset int) string {
decodedSecret, err := base32.StdEncoding.WithPadding(base32.NoPadding).DecodeString(secret)
if err != nil {
fmt.Fprintf(os.Stderr, "WARN: Invalid Base32 secret\n")
}
counter := time.Now().Unix() / TIME_STEP - int64(timeStepOffset) counter := time.Now().Unix() / TIME_STEP - int64(timeStepOffset)
counterBytes := make([]byte, 8) counterBytes := make([]byte, 8)
binary.BigEndian.PutUint64(counterBytes, uint64(counter)) binary.BigEndian.PutUint64(counterBytes, uint64(counter))
mac := hmac.New(sha1.New, []byte(secret)) mac := hmac.New(sha1.New, []byte(decodedSecret))
mac.Write(counterBytes) mac.Write(counterBytes)
hash := mac.Sum(nil) hash := mac.Sum(nil)
@ -33,6 +42,18 @@ func GenerateTOTP(secret string, timeStepOffset int) string {
return fmt.Sprintf(fmt.Sprintf("%%0%dd", CODE_LENGTH), code) return fmt.Sprintf(fmt.Sprintf("%%0%dd", CODE_LENGTH), code)
} }
func GenerateTOTPSecret(length int) string {
bytes := make([]byte, length)
_, err := rand.Read(bytes)
if err != nil {
panic("FATAL: Failed to generate random TOTP bytes")
}
secret := base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(bytes)
return strings.ToUpper(secret)
}
func GenerateTOTPURI(username string, secret string) string { func GenerateTOTPURI(username string, secret string) string {
url := url.URL{ url := url.URL{
Scheme: "otpauth", Scheme: "otpauth",

View file

@ -80,7 +80,7 @@ func main() {
} }
username := os.Args[2] username := os.Args[2]
totpName := os.Args[3] totpName := os.Args[3]
secret := controller.GenerateAlnumString(32) secret := controller.GenerateTOTPSecret(controller.TOTP_SECRET_LENGTH)
account, err := controller.GetAccount(global.DB, username) account, err := controller.GetAccount(global.DB, username)
if err != nil { if err != nil {