def generate_hmac_sha1_signature(base_string, client_shared_secret, token_shared_secret=None): """ Calculates an HMAC-SHA1 signature for a base string. :see: HMAC-SHA1 (http://tools.ietf.org/html/rfc5849#section-3.4.2) :param base_string: Base string. :param client_shared_secret: Client (consumer) shared secret. :param token_shared_secret: Token/temporary credentials shared secret if available. :returns: HMAC-SHA1 signature. """ key = _generate_plaintext_signature(client_shared_secret, token_shared_secret) return hmac_sha1_base64_digest(key, base_string)
def verify_hmac_sha1_signature(signature, base_string, client_shared_secret, token_shared_secret=None, debug=False): """ Verifies an HMAC-SHA1 signature for a base string. :see: HMAC-SHA1 (http://tools.ietf.org/html/rfc5849#section-3.4.2) :param signature: The signature to verify. :param base_string: The base string. :param client_shared_secret: Client (consumer) shared secret. :param token_shared_secret: Token/temporary credentials shared secret if available. :param debug: Default ``False``. ``True`` to turn on debugging mode, which attempts to find out why signature verification fails, if it does; ``False`` otherwise. :returns: A tuple of (whether signature matches (boolean), error message (None if it succeeded)). """ key = _generate_plaintext_signature(client_shared_secret, token_shared_secret) check_ok = (signature == hmac_sha1_base64_digest(key, base_string)) if check_ok: err = None else: err = "Invalid signature" if not check_ok and debug: # Try to find out why it didn't match. # We need to help the poor human souls on the other # side of this mess who are trying to debug their OAuth clients. # This is not going to detect 100% of the cases, because it is # too easy to screw up on the client side. Anything could be wrong. # We're just trying to find out some common problems. # Assume correct base string but detect incorrect signature encoding. key = _generate_plaintext_signature(client_shared_secret, token_shared_secret, _percent_encode=False) if signature == hmac_sha1_base64_digest(key, base_string): return check_ok, "Invalid signature: signature elements " \ "are not percent-encoded properly" # Assume correct base string but detect missing ampersands in signature. if client_shared_secret and not token_shared_secret: key = percent_encode(client_shared_secret) + SYMBOL_AMPERSAND if signature == hmac_sha1_base64_digest(key, base_string): return check_ok, "Invalid signature: missing ampersand `&` " \ "after client shared secret in signature" elif not client_shared_secret and token_shared_secret: key = SYMBOL_AMPERSAND + percent_encode(token_shared_secret) if signature == hmac_sha1_base64_digest(key, base_string): return check_ok, "Invalid signature: missing ampersand `&` "\ "before token secret in signature" elif not client_shared_secret and not token_shared_secret: key = SYMBOL_AMPERSAND if signature == hmac_sha1_base64_digest(key, base_string): return check_ok, "Invalid signature: missing ampersand `&` "\ "without secrets in signature" elif client_shared_secret and token_shared_secret: key = percent_encode(client_shared_secret) + \ SYMBOL_AMPERSAND + percent_encode(token_shared_secret) if signature == hmac_sha1_base64_digest(key, base_string): return check_ok, "Invalid signature: missing ampersand `&` "\ "between signature secrets" # Assume incorrect base string return check_ok, "Invalid signature: check base string?" return check_ok, err
def test_value(self): self.assertEqual(hmac_sha1_base64_digest(key, base_string), expected_hmac_sha1_base64_digest)
def test_value(self): self.assertEqual(hash.hmac_sha1_base64_digest(KEY, BASE_STRING), EXPECTED_HMAC_SHA1_BASE64_DIGEST)