totp codes don't seem to sync but they're here!!
This commit is contained in:
parent
5e493554dc
commit
ae254dd731
7 changed files with 345 additions and 27 deletions
108
controller/totp.go
Normal file
108
controller/totp.go
Normal file
|
@ -0,0 +1,108 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"arimelody-web/model"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
const TIME_STEP int64 = 30
|
||||
const CODE_LENGTH = 6
|
||||
|
||||
func GenerateTOTP(secret string, timeStepOffset int) string {
|
||||
counter := time.Now().Unix() / TIME_STEP - int64(timeStepOffset)
|
||||
counterBytes := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(counterBytes, uint64(counter))
|
||||
|
||||
mac := hmac.New(sha1.New, []byte(secret))
|
||||
mac.Write(counterBytes)
|
||||
hash := mac.Sum(nil)
|
||||
|
||||
offset := hash[len(hash) - 1] & 0x0f
|
||||
binaryCode := int32(binary.BigEndian.Uint32(hash[offset : offset + 4]) & 0x7FFFFFFF)
|
||||
code := binaryCode % int32(math.Pow10(CODE_LENGTH))
|
||||
|
||||
return fmt.Sprintf(fmt.Sprintf("%%0%dd", CODE_LENGTH), code)
|
||||
}
|
||||
|
||||
func GenerateTOTPURI(username string, secret string) string {
|
||||
url := url.URL{
|
||||
Scheme: "otpauth",
|
||||
Host: "totp",
|
||||
Path: url.QueryEscape("arimelody.me") + ":" + url.QueryEscape(username),
|
||||
}
|
||||
|
||||
query := url.Query()
|
||||
query.Set("secret", secret)
|
||||
query.Set("issuer", "arimelody.me")
|
||||
query.Set("algorithm", "SHA1")
|
||||
query.Set("digits", fmt.Sprintf("%d", CODE_LENGTH))
|
||||
query.Set("period", fmt.Sprintf("%d", TIME_STEP))
|
||||
url.RawQuery = query.Encode()
|
||||
|
||||
return url.String()
|
||||
}
|
||||
|
||||
func GetTOTPsForAccount(db *sqlx.DB, accountID string) ([]model.TOTP, error) {
|
||||
totps := []model.TOTP{}
|
||||
|
||||
err := db.Select(
|
||||
&totps,
|
||||
"SELECT * FROM totp " +
|
||||
"WHERE account=$1 " +
|
||||
"ORDER BY created_at ASC",
|
||||
accountID,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return totps, nil
|
||||
}
|
||||
|
||||
func GetTOTP(db *sqlx.DB, accountID string, name string) (*model.TOTP, error) {
|
||||
totp := model.TOTP{}
|
||||
|
||||
err := db.Get(
|
||||
&totp,
|
||||
"SELECT * FROM totp " +
|
||||
"WHERE account=$1",
|
||||
accountID,
|
||||
)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "no rows") {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &totp, nil
|
||||
}
|
||||
|
||||
func CreateTOTP(db *sqlx.DB, totp *model.TOTP) error {
|
||||
_, err := db.Exec(
|
||||
"INSERT INTO totp (account, name, secret) " +
|
||||
"VALUES ($1,$2,$3)",
|
||||
totp.AccountID,
|
||||
totp.Name,
|
||||
totp.Secret,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func DeleteTOTP(db *sqlx.DB, accountID string, name string) error {
|
||||
_, err := db.Exec(
|
||||
"DELETE FROM totp WHERE account=$1 AND name=$2",
|
||||
accountID,
|
||||
name,
|
||||
)
|
||||
return err
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue