"""HMAC Signature. This library handles the HMAC signature of a request. This assumes the request is an object created using the python-requests library. The HMAC Signature is done in 3 steps: * Create a random string of 30 characters. * Create calculate the HMAC from the request. * Save the HMAC in a datastorage. If the HMAC Signature has to be verified, the reverse is done: fetch the HMAC and secret from the datastorage, and compare it against the HMAC of the incoming request. """ import hashlib import hmac import random import string from warnings import warn from owsrequest import text SECRET_SIZE = 30 SECRET_CHARACTERS = string.ascii_letters + string.digits HMAC_FORMAT = '{verb}\n{body}\n{cid}\n{resource}' def create_secret(size=None): """Create the secret. The secret is a 30 characters long string that contains number, letters and is case sensitive. This secret will be used to calculate the HMAC. Args: size (int): the size of the secret. Returns: str: the secret. """ warn('HMAC Authorization is being deprecated', PendingDeprecationWarning, stacklevel=2) size = size or SECRET_SIZE return ''.join(random.choice(SECRET_CHARACTERS) for i in range(size)) def calculate(secret, http_verb, http_body, correlation_id, resource): """Calculate the HMAC Signature. Args: secret (str): the 30 characters long secret. http_verb (str): the verb used for the transaction. http_body (str): the body of the request. correlation_id (str): the correlation id that will be send as part of the request. resource (str): the url of the resource. Returns: str: the hmac. """ warn('HMAC Authorization is being deprecated', PendingDeprecationWarning, stacklevel=2) message = HMAC_FORMAT.format( verb=http_verb.upper(), body=calculate_body_md5(http_body), cid=correlation_id, resource=resource) return hmac.new( text.to_bytes(secret), text.to_bytes(message), digestmod='sha1').hexdigest() def calculate_body_md5(http_body): """Calculate the body's MD5. Args: http_body (str): the body of the request. Returns: str: the hexdigest of the http body or empty string if the http body was null. """ warn('HMAC Authorization is being deprecated', PendingDeprecationWarning, stacklevel=2) if not http_body: return '' return hashlib.md5(text.to_bytes(http_body)).hexdigest()