signature.go 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. package security
  2. import (
  3. "crypto/hmac"
  4. "crypto/sha256"
  5. "encoding/base64"
  6. "errors"
  7. "github.com/imgproxy/imgproxy/v3/config"
  8. )
  9. var (
  10. ErrInvalidSignature = errors.New("Invalid signature")
  11. ErrInvalidSignatureEncoding = errors.New("Invalid signature encoding")
  12. )
  13. func VerifySignature(signature, path string) error {
  14. if len(config.Keys) == 0 || len(config.Salts) == 0 {
  15. return nil
  16. }
  17. for _, s := range config.TrustedSignatures {
  18. if s == signature {
  19. return nil
  20. }
  21. }
  22. messageMAC, err := base64.RawURLEncoding.DecodeString(signature)
  23. if err != nil {
  24. return ErrInvalidSignatureEncoding
  25. }
  26. for i := 0; i < len(config.Keys); i++ {
  27. if hmac.Equal(messageMAC, signatureFor(path, config.Keys[i], config.Salts[i], config.SignatureSize)) {
  28. return nil
  29. }
  30. }
  31. return ErrInvalidSignature
  32. }
  33. func signatureFor(str string, key, salt []byte, signatureSize int) []byte {
  34. mac := hmac.New(sha256.New, key)
  35. mac.Write(salt)
  36. mac.Write([]byte(str))
  37. expectedMAC := mac.Sum(nil)
  38. if signatureSize < 32 {
  39. return expectedMAC[:signatureSize]
  40. }
  41. return expectedMAC
  42. }