@@ -0,0 +1,1934 @@
+# encoding: utf-8%0A%0Aimport hmac%0Aimport json%0Aimport base64%0Aimport collections%0A%0Afrom waterbutler import settings%0A%0A%0A# Written by @jmcarp originally%0Adef order_recursive(data):%0A    %22%22%22Recursively sort keys of input data and all its nested dictionaries.%0A    Used to ensure consistent ordering of JSON payloads.%0A    %22%22%22%0A    if isinstance(data, dict):%0A        return collections.OrderedDict(%0A            sorted(%0A                (%0A                    (key, order_recursive(value))%0A                    for key, value in data.items()%0A                ),%0A                key=lambda item: item%5B0%5D%0A            )%0A        )%0A    if isinstance(data, list):%0A        return %5B%0A            order_recursive(value)%0A            for value in data%0A        %5D%0A    return data%0A%0A%0Adef serialize_payload(payload):%0A    ordered = order_recursive(payload)%0A    return base64.b64encode(json.dumps(ordered).encode('UTF-8'))%0A%0A%0Adef unserialize_payload(message):%0A    payload = json.loads(base64.b64decode(message))%0A    return order_recursive(payload)%0A%0A%0Aclass Signer(object):%0A%0A    def __init__(self, secret, digest):%0A        assert callable(digest)%0A        self.secret = secret%0A        self.digest = digest%0A%0A    def sign_message(self, message):%0A        return hmac.new(%0A            key=self.secret,%0A            digestmod=self.digest,%0A            msg=message,%0A        ).hexdigest()%0A%0A    def sign_payload(self, payload):%0A        message = serialize_payload(payload)%0A        signature = self.sign_message(message)%0A        return message, signature%0A%0A    def verify_message(self, signature, message):%0A        expected = self.sign_message(message)%0A        return signature == expected%0A%0A    def verify_payload(self, signature, payload):%0A        _, expected = self.sign_payload(payload)%0A        return signature == expected%0A%0A%0A# default_signer = Signer(settings.DEFAULT_HMAC_KEY, settings.DEFAULT_HMAC_ALGORITHM)%0Aosf_signer = Signer(settings.OSF_HMAC_SECRET, settings.OSF_HMAC_ALGORITHM)%0A

Add signing thanks @jmcarp