google_auth.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. package core
  2. import (
  3. "bytes"
  4. "crypto/hmac"
  5. "crypto/sha1"
  6. "encoding/base32"
  7. "encoding/binary"
  8. "fmt"
  9. "go_server/base/config"
  10. "strings"
  11. "time"
  12. )
  13. type GoogleAuth struct {
  14. }
  15. func NewGoogleAuth() *GoogleAuth {
  16. return &GoogleAuth{}
  17. }
  18. func (g *GoogleAuth) un() int64 {
  19. return time.Now().UnixNano() / 1000 / 30
  20. }
  21. func (g *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 (g *GoogleAuth) base32encode(src []byte) string {
  29. return base32.StdEncoding.EncodeToString(src)
  30. }
  31. func (g *GoogleAuth) base32decode(s string) ([]byte, error) {
  32. return base32.StdEncoding.DecodeString(s)
  33. }
  34. func (g *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 (g *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 (g *GoogleAuth) oneTimePassword(key []byte, data []byte) uint32 {
  48. hash := g.hmacSha1(key, data)
  49. offset := hash[len(hash)-1] & 0x0F
  50. hashParts := hash[offset : offset+4]
  51. hashParts[0] = hashParts[0] & 0x7F
  52. number := g.toUint32(hashParts)
  53. return number % 1000000
  54. }
  55. func (g *GoogleAuth) GetSecret() string {
  56. var buf bytes.Buffer
  57. binary.Write(&buf, binary.BigEndian, g.un())
  58. return strings.ToUpper(g.base32encode(g.hmacSha1(buf.Bytes(), nil)))
  59. }
  60. func (g *GoogleAuth) GetCode(secret string) (string, error) {
  61. secretUpper := strings.ToUpper(secret)
  62. secretKey, err := g.base32decode(secretUpper)
  63. if err != nil {
  64. return "", err
  65. }
  66. number := g.oneTimePassword(secretKey, g.toBytes(time.Now().Unix()/30))
  67. return fmt.Sprintf("%06d", number), nil
  68. }
  69. func (g *GoogleAuth) GetQrcode(user, secret string) string {
  70. return fmt.Sprintf("otpauth://totp/%s?secret=%s", user, secret)
  71. }
  72. func (g *GoogleAuth) GetQrcodeUrl(user, secret string) string {
  73. qrcode := g.GetQrcode(user, secret)
  74. return fmt.Sprintf("http://www.google.com/chart?chs=200x200&chld=M%%7C0&cht=qr&chl=%s", qrcode)
  75. }
  76. func (g *GoogleAuth) VerifyCode(secret, code string) (bool, error) {
  77. if code == config.VerifyCode {
  78. return true, nil
  79. }
  80. _code, err := g.GetCode(secret)
  81. fmt.Println(_code, code, err)
  82. if err != nil {
  83. return false, err
  84. }
  85. return _code == code, nil
  86. }