google.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package auth
  2. import (
  3. "bytes"
  4. "crypto/hmac"
  5. "crypto/sha1"
  6. "encoding/base32"
  7. "encoding/binary"
  8. "fmt"
  9. "net/url"
  10. "strings"
  11. "time"
  12. )
  13. type GoogleAuth struct {
  14. }
  15. func NewGoogleAuth() *GoogleAuth {
  16. return &GoogleAuth{}
  17. }
  18. func (googleAuth *GoogleAuth) un() int64 {
  19. return time.Now().UnixNano() / 1000 / 30
  20. }
  21. func (googleauth *GoogleAuth) hmacSha1(key, data []byte) []byte {
  22. h := hmac.New(sha1.New, key)
  23. if total := len(data); total > 0 {
  24. h.Write(data)
  25. }
  26. return h.Sum(nil)
  27. }
  28. func (googleauth *GoogleAuth) base32encode(src []byte) string {
  29. return base32.StdEncoding.EncodeToString(src)
  30. }
  31. func (googleauth *GoogleAuth) base32decode(s string) ([]byte, error) {
  32. return base32.StdEncoding.DecodeString(s)
  33. }
  34. func (googleauth *GoogleAuth) toBytes(value int64) []byte {
  35. var result []byte
  36. mask := int64(0xFF)
  37. shifts := [8]uint16{56, 48, 40, 32, 24, 16, 8, 0}
  38. for _, shift := range shifts {
  39. result = append(result, byte((value>>shift)&mask))
  40. }
  41. return result
  42. }
  43. func (googleauth *GoogleAuth) toUint32(bts []byte) uint32 {
  44. return (uint32(bts[0]) << 24) + (uint32(bts[1]) << 16) +
  45. (uint32(bts[2]) << 8) + uint32(bts[3])
  46. }
  47. func (googleauth *GoogleAuth) oneTimePassword(key []byte, data []byte) uint32 {
  48. hash := googleauth.hmacSha1(key, data)
  49. offset := hash[len(hash)-1] & 0x0F
  50. hashParts := hash[offset : offset+4]
  51. hashParts[0] = hashParts[0] & 0x7F
  52. number := googleauth.toUint32(hashParts)
  53. return number % 1000000
  54. }
  55. // 获取秘钥
  56. func (googleauth *GoogleAuth) GetSecret() string {
  57. var buf bytes.Buffer
  58. binary.Write(&buf, binary.BigEndian, googleauth.un())
  59. return strings.ToUpper(googleauth.base32encode(googleauth.hmacSha1(buf.Bytes(), nil)))
  60. }
  61. func (googleauth *GoogleAuth) GetSecretByStr(str string) string {
  62. var buf bytes.Buffer
  63. binary.Write(&buf, binary.BigEndian, googleauth.un())
  64. return strings.ToUpper(googleauth.base32encode([]byte(str)))
  65. }
  66. // 获取动态码
  67. func (googleauth *GoogleAuth) GetCode(secret string) (string, error) {
  68. secretUpper := strings.ToUpper(secret)
  69. secretKey, err := googleauth.base32decode(secretUpper)
  70. if err != nil {
  71. return "", err
  72. }
  73. number := googleauth.oneTimePassword(secretKey, googleauth.toBytes(time.Now().Unix()/30))
  74. return fmt.Sprintf("%06d", number), nil
  75. }
  76. // 获取动态码二维码内容
  77. func (googleauth *GoogleAuth) GetQrcode(user, secret string) string {
  78. return fmt.Sprintf("otpauth://totp/%s?secret=%s", user, secret)
  79. }
  80. // 获取动态码二维码图片地址,这里是第三方二维码api
  81. func (googleauth *GoogleAuth) GetQrcodeUrl(user, secret string) string {
  82. qrcode := googleauth.GetQrcode(user, secret)
  83. width := "200"
  84. height := "200"
  85. data := url.Values{}
  86. data.Set("data", qrcode)
  87. return "https://api.qrserver.com/v1/create-qr-code/?" + data.Encode() + "&size=" + width + "x" + height + "&ecc=M"
  88. }
  89. // 验证动态码
  90. func (googleauth *GoogleAuth) VerifyCode(secret, code string) (bool, error) {
  91. _code, err := googleauth.GetCode(secret)
  92. fmt.Println(_code, code, err)
  93. if err != nil {
  94. return false, err
  95. }
  96. return _code == code, nil
  97. }