signature.go 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. package security
  2. import (
  3. "crypto/hmac"
  4. "crypto/sha256"
  5. "encoding/base64"
  6. "slices"
  7. )
  8. func (s *Checker) VerifySignature(signature, path string) error {
  9. if len(s.config.Keys) == 0 || len(s.config.Salts) == 0 {
  10. return nil
  11. }
  12. if slices.Contains(s.config.TrustedSignatures, signature) {
  13. return nil
  14. }
  15. messageMAC, err := base64.RawURLEncoding.DecodeString(signature)
  16. if err != nil {
  17. return newSignatureError("Invalid signature encoding")
  18. }
  19. for i := 0; i < len(s.config.Keys); i++ {
  20. if hmac.Equal(messageMAC, signatureFor(path, s.config.Keys[i], s.config.Salts[i], s.config.SignatureSize)) {
  21. return nil
  22. }
  23. }
  24. return newSignatureError("Invalid signature")
  25. }
  26. func signatureFor(str string, key, salt []byte, signatureSize int) []byte {
  27. mac := hmac.New(sha256.New, key)
  28. mac.Write(salt)
  29. // It's supposed that path starts with '/'. However, if and input path comes with the
  30. // leading slash split, let's re-add it here.
  31. if str[0] != '/' {
  32. mac.Write([]byte{'/'})
  33. }
  34. mac.Write([]byte(str))
  35. expectedMAC := mac.Sum(nil)
  36. if signatureSize < 32 {
  37. return expectedMAC[:signatureSize]
  38. }
  39. return expectedMAC
  40. }