signature_service.py 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940
  1. import hashlib
  2. import hmac
  3. import time
  4. from typing import Dict, Any
  5. class SignatureService:
  6. @staticmethod
  7. def verify_signature(secret: str, params: Dict[str, Any], sign: str, tolerance: int = 300) -> bool:
  8. """
  9. Verifies the signature of the request.
  10. Algorithm:
  11. 1. Check timestamp freshness (tolerance seconds).
  12. 2. Sort keys alphabetically.
  13. 3. Concatenate key=value&key=value...
  14. 4. Calculate HMAC-SHA256 with secret.
  15. 5. Compare with sign.
  16. """
  17. # 1. Check timestamp
  18. ts = int(params.get("timestamp", 0))
  19. now = int(time.time())
  20. if abs(now - ts) > tolerance:
  21. return False
  22. # 2. Prepare string to sign
  23. # Filter out 'sign' itself and empty values if any? usually we sign all except signature
  24. data_to_sign = {k: v for k, v in params.items() if k != "sign"}
  25. sorted_keys = sorted(data_to_sign.keys())
  26. query_string = "&".join([f"{k}={data_to_sign[k]}" for k in sorted_keys])
  27. # 3. Calculate HMAC
  28. calculated_sign = hmac.new(
  29. secret.encode('utf-8'),
  30. query_string.encode('utf-8'),
  31. hashlib.sha256
  32. ).hexdigest()
  33. return hmac.compare_digest(calculated_sign, sign)