import hashlib import hmac import time from typing import Dict, Any class SignatureService: @staticmethod def verify_signature(secret: str, params: Dict[str, Any], sign: str, tolerance: int = 300) -> bool: """ Verifies the signature of the request. Algorithm: 1. Check timestamp freshness (tolerance seconds). 2. Sort keys alphabetically. 3. Concatenate key=value&key=value... 4. Calculate HMAC-SHA256 with secret. 5. Compare with sign. """ # 1. Check timestamp ts = int(params.get("timestamp", 0)) now = int(time.time()) if abs(now - ts) > tolerance: return False # 2. Prepare string to sign # Filter out 'sign' itself and empty values if any? usually we sign all except signature data_to_sign = {k: v for k, v in params.items() if k != "sign"} sorted_keys = sorted(data_to_sign.keys()) query_string = "&".join([f"{k}={data_to_sign[k]}" for k in sorted_keys]) # 3. Calculate HMAC calculated_sign = hmac.new( secret.encode('utf-8'), query_string.encode('utf-8'), hashlib.sha256 ).hexdigest() return hmac.compare_digest(calculated_sign, sign)