import hashlib import hmac import base64 import time from collections import OrderedDict try: from urllib.parse import urlencode except ImportError: from urllib import urlencode class SignedRequest: def __init__(self, requestSignature, requestTimestamp, requestBody, requestParameters): self._requestSignature = requestSignature self._requestTimestamp = str(requestTimestamp) self._requestBody = requestBody self._requestParameters = requestParameters def verify(self, signing_key): payload = self._build_payload() expected_signature = base64.b64decode(self._requestSignature) calculated_signature = hmac.new(signing_key.encode('latin-1'), payload.encode('latin-1'), hashlib.sha256).digest() return expected_signature == calculated_signature def is_recent(self, offset=10): return int(time.time()) - int(self._requestTimestamp) < offset def _build_payload(self): checksum_body = hashlib.sha256(self._requestBody.encode('latin-1')).digest() str_checksum_body = checksum_body.decode('latin-1') parts = [self._requestTimestamp, urlencode(self._sort_dict(self._requestParameters), True), str_checksum_body] return "\n".join(parts) def _sort_dict(self, dict): sorted_dict = OrderedDict() for key in sorted(dict): sorted_dict[key] = dict[key] return sorted_dict