hmac.go 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. package sign
  2. import (
  3. "crypto/hmac"
  4. "crypto/sha256"
  5. "encoding/base64"
  6. "io"
  7. "strconv"
  8. "strings"
  9. "time"
  10. )
  11. type HMACSign struct {
  12. SecretKey []byte
  13. }
  14. func (s HMACSign) Sign(data string, expire int64) string {
  15. h := hmac.New(sha256.New, s.SecretKey)
  16. expireTimeStamp := strconv.FormatInt(expire, 10)
  17. _, err := io.WriteString(h, data+":"+expireTimeStamp)
  18. if err != nil {
  19. return ""
  20. }
  21. return base64.URLEncoding.EncodeToString(h.Sum(nil)) + ":" + expireTimeStamp
  22. }
  23. func (s HMACSign) Verify(data, sign string) error {
  24. signSlice := strings.Split(sign, ":")
  25. // check whether contains expire time
  26. if signSlice[len(signSlice)-1] == "" {
  27. return ErrExpireMissing
  28. }
  29. // check whether expire time is expired
  30. expires, err := strconv.ParseInt(signSlice[len(signSlice)-1], 10, 64)
  31. if err != nil {
  32. return ErrExpireInvalid
  33. }
  34. // if expire time is expired, return error
  35. if expires < time.Now().Unix() && expires != 0 {
  36. return ErrSignExpired
  37. }
  38. // verify sign
  39. if s.Sign(data, expires) != sign {
  40. return ErrSignInvalid
  41. }
  42. return nil
  43. }
  44. func NewHMACSign(secret []byte) Sign {
  45. return HMACSign{SecretKey: secret}
  46. }