1. 服务端代码:

     package main
     import (
         "bytes"
         "crypto/hmac"
         "crypto/sha1"
         "encoding/base32"
         "encoding/binary"
         "fmt"
         "strings"
         "time"
     )
     type GoogleAuth struct {
     }
     func NewGoogleAuth() *GoogleAuth {
         return &GoogleAuth{}
     }
     func (this *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 (this *GoogleAuth) base32encode(src []byte) string {
         return base32.StdEncoding.EncodeToString(src)
     }
     func (this *GoogleAuth) base32decode(s string) ([]byte, error) {
         return base32.StdEncoding.DecodeString(s)
     }
     func (this *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 (this *GoogleAuth) toUint32(bts []byte) uint32 {
         return (uint32(bts[0]) << 24) + (uint32(bts[1]) << 16) +
             (uint32(bts[2]) << 8) + uint32(bts[3])
     }
     func (this *GoogleAuth) oneTimePassword(key []byte, data []byte) uint32 {
         hash := this.hmacSha1(key, data)
         offset := hash[len(hash)-1] & 0x0F
         hashParts := hash[offset : offset+4]
         hashParts[0] = hashParts[0] & 0x7F
         number := this.toUint32(hashParts)
         return number % 1000000
     }
     func (this *GoogleAuth) GenerateSecret() string {
         var buf bytes.Buffer
         binary.Write(&buf, binary.BigEndian, time.Now().UnixNano()/1000/30)
         return strings.ToUpper(this.base32encode(this.hmacSha1(buf.Bytes(), nil)))
     }
     func (this *GoogleAuth) GetCode(secret string) (string, error) {
         secretUpper := strings.ToUpper(secret)
         secretKey, err := this.base32decode(secretUpper)
         if err != nil {
             return "", err
         }
         number := this.oneTimePassword(secretKey, this.toBytes(time.Now().Unix()/30))
         return fmt.Sprintf("%06d", number), nil
     }
     func (this *GoogleAuth) VerifyCode(secret, code string) (bool, error) {
         _code, err := this.GetCode(secret)
         if err != nil {
             return false, err
         }
         return _code == code, nil
     }
     func main() {
         obj := NewGoogleAuth()
         // 生成密钥
         secret := obj.GenerateSecret()
         fmt.Println("secret:", secret)
         // 通过密钥生成数字码
         code, err := obj.GetCode(secret)
         fmt.Println("Code:", code, err)
         // 验证
         ok, err := obj.VerifyCode(secret, code)
         fmt.Println(ok, err)
     }
  2. 客户端:

    1. 安装:
    2. 添加密钥:


    3. 效果:
文档更新时间: 2024-04-19 15:11   作者:lee