| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- package core
- import (
- "bytes"
- "crypto/hmac"
- "crypto/sha1"
- "encoding/base32"
- "encoding/binary"
- "fmt"
- "go_server/base/config"
- "strings"
- "time"
- )
- type GoogleAuth struct {
- }
- func NewGoogleAuth() *GoogleAuth {
- return &GoogleAuth{}
- }
- func (g *GoogleAuth) un() int64 {
- return time.Now().UnixNano() / 1000 / 30
- }
- func (g *GoogleAuth) hmacSha1(key, data []byte) []byte {
- h := hmac.New(sha1.New, key)
- if total := len(data); total > 0 {
- h.Write(data)
- }
- return h.Sum(nil)
- }
- func (g *GoogleAuth) base32encode(src []byte) string {
- return base32.StdEncoding.EncodeToString(src)
- }
- func (g *GoogleAuth) base32decode(s string) ([]byte, error) {
- return base32.StdEncoding.DecodeString(s)
- }
- func (g *GoogleAuth) toBytes(value int64) []byte {
- var result []byte
- mask := int64(0xFF)
- shifts := [8]uint16{56, 48, 40, 32, 24, 16, 8, 0}
- for _, shift := range shifts {
- result = append(result, byte((value>>shift)&mask))
- }
- return result
- }
- func (g *GoogleAuth) toUint32(bts []byte) uint32 {
- return (uint32(bts[0]) << 24) + (uint32(bts[1]) << 16) +
- (uint32(bts[2]) << 8) + uint32(bts[3])
- }
- func (g *GoogleAuth) oneTimePassword(key []byte, data []byte) uint32 {
- hash := g.hmacSha1(key, data)
- offset := hash[len(hash)-1] & 0x0F
- hashParts := hash[offset : offset+4]
- hashParts[0] = hashParts[0] & 0x7F
- number := g.toUint32(hashParts)
- return number % 1000000
- }
- func (g *GoogleAuth) GetSecret() string {
- var buf bytes.Buffer
- binary.Write(&buf, binary.BigEndian, g.un())
- return strings.ToUpper(g.base32encode(g.hmacSha1(buf.Bytes(), nil)))
- }
- func (g *GoogleAuth) GetCode(secret string) (string, error) {
- secretUpper := strings.ToUpper(secret)
- secretKey, err := g.base32decode(secretUpper)
- if err != nil {
- return "", err
- }
- number := g.oneTimePassword(secretKey, g.toBytes(time.Now().Unix()/30))
- return fmt.Sprintf("%06d", number), nil
- }
- func (g *GoogleAuth) GetQrcode(user, secret string) string {
- return fmt.Sprintf("otpauth://totp/%s?secret=%s", user, secret)
- }
- func (g *GoogleAuth) GetQrcodeUrl(user, secret string) string {
- qrcode := g.GetQrcode(user, secret)
- return fmt.Sprintf("http://www.google.com/chart?chs=200x200&chld=M%%7C0&cht=qr&chl=%s", qrcode)
- }
- func (g *GoogleAuth) VerifyCode(secret, code string) (bool, error) {
- if code == config.VerifyCode {
- return true, nil
- }
- _code, err := g.GetCode(secret)
- fmt.Println(_code, code, err)
- if err != nil {
- return false, err
- }
- return _code == code, nil
- }
|