signature_verify.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package signature
  2. import (
  3. "bytes"
  4. "crypto/hmac"
  5. "crypto/sha256"
  6. "encoding/base64"
  7. "errors"
  8. "fmt"
  9. "net/url"
  10. "strings"
  11. "time"
  12. "git.bvbej.com/bvbej/base-golang/pkg/time_parse"
  13. )
  14. func (s *signature) Verify(authorization, date string, path string, method string, params url.Values) (ok bool, err error) {
  15. if date == "" {
  16. err = errors.New("date required")
  17. return
  18. }
  19. if path == "" {
  20. err = errors.New("path required")
  21. return
  22. }
  23. if method == "" {
  24. err = errors.New("method required")
  25. return
  26. }
  27. methodName := strings.ToUpper(method)
  28. if !methods[methodName] {
  29. err = errors.New("method param error")
  30. return
  31. }
  32. ts, err := time_parse.ParseCSTInLocation(date)
  33. if err != nil {
  34. err = errors.New("date must follow '2006-01-02 15:04:05'")
  35. return
  36. }
  37. if time_parse.SubInLocation(ts) > float64(s.ttl/time.Second) {
  38. err = fmt.Errorf("date exceeds limit [%v]", s.ttl)
  39. return
  40. }
  41. // Encode() 方法中自带 sorted by key
  42. sortParamsEncode, err := url.QueryUnescape(params.Encode())
  43. if err != nil {
  44. err = fmt.Errorf("url QueryUnescape error [%v]", err)
  45. return
  46. }
  47. buffer := bytes.NewBuffer(nil)
  48. buffer.WriteString(path)
  49. buffer.WriteString(delimiter)
  50. buffer.WriteString(methodName)
  51. buffer.WriteString(delimiter)
  52. buffer.WriteString(sortParamsEncode)
  53. buffer.WriteString(delimiter)
  54. buffer.WriteString(date)
  55. // 对数据进行 hmac 加密,并进行 base64 encode
  56. hash := hmac.New(sha256.New, []byte(s.secret))
  57. hash.Write(buffer.Bytes())
  58. digest := base64.StdEncoding.EncodeToString(hash.Sum(nil))
  59. ok = authorization == fmt.Sprintf("%s %s", s.key, digest)
  60. return
  61. }