def sign_request(request, id, key, hashmod=None, params=None): """Sign the given request using MAC access authentication. This function implements the client-side request signing algorithm as expected by the server, i.e. MAC access authentication as defined by RFC-TODO. It takes a WebOb Request object and inserts the appropriate signature into its Authorization header. """ # Use explicitly-given parameters, or those from the request. if params is None: params = utils.parse_authz_header(request, {}) if params and params.pop("scheme") != "MAC": params.clear() # Give sensible values to any parameters that weren't specified. params["id"] = id if "ts" not in params: params["ts"] = str(int(time.time())) if "nonce" not in params: params["nonce"] = utils.b64encode(os.urandom(5)) # Calculate the signature and add it to the parameters. params["mac"] = get_signature(request, key, hashmod, params) # Serialize the parameters back into the authz header, and return it. # WebOb has logic to do this that's not perfect, but good enough for us. request.authorization = ("MAC", params) return request.headers["Authorization"]
def get_signature(request, key, hashmod=None, params=None): """Get the MAC signature for the given request. This function calculates the MAC signature for the given request and returns it as a string. If the "params" parameter is not None, it is assumed to be a pre-parsed dict of MAC parameters as one might find in the Authorization header. If it is missing or None then the Authorization header from the request will be parsed to determine the necessary parameters. """ if params is None: params = utils.parse_authz_header(request, {}) if hashmod is None: hashmod = sha1 sigstr = utils.get_normalized_request_string(request, params) # The spec mandates that ids and keys must be ascii. # It's therefore safe to encode like this before doing the signature. sigstr = sigstr.encode("ascii") key = key.encode("ascii") return utils.b64encode(hmac.new(key, sigstr, hashmod).digest())