working TOTP codes YIPPEE
This commit is contained in:
parent
7044f7344b
commit
39b332b477
|
@ -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",
|
||||||
|
|
2
main.go
2
main.go
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue