You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Andrey Kislyuk aff77a5db3 Update actions 3 weeks ago
.github Update actions 3 weeks ago
docs Use isort and black 7 months ago
requests_http_signature Use isort and black 7 months ago
test Use isort and black 7 months ago
.gitignore Begin requests-http-signature 6 years ago
Changes.rst v0.7.1 11 months ago
LICENSE Begin requests-http-signature 6 years ago
Makefile Use mypy check-untyped-defs 11 months ago
README.rst fix(readme): updated HTTPSignatureAuth arguments (#34) 11 months ago Use gh to manage releases 3 weeks ago
pyproject.toml Update isort config 7 months ago
setup.cfg Update package to follow the latest draft 12 months ago Fix typo in package data manifest 5 months ago


requests-http-signature: A Requests auth module for HTTP Signature
**requests-http-signature** is a `Requests <>`_ `authentication plugin
<>`_ (``requests.auth.AuthBase`` subclass) implementing
the `IETF HTTP Message Signatures draft standard <>`_.


$ pip install requests-http-signature


.. code-block:: python

import requests
from requests_http_signature import HTTPSignatureAuth, algorithms

preshared_key_id = 'squirrel'
preshared_secret = b'monorail_cat'
url = ''

auth = HTTPSignatureAuth(key=preshared_secret,
requests.get(url, auth=auth)

By default, only the ``Date`` header and the ``@method``, ``@authority``, and ``@target-uri`` derived component
identifiers are signed for body-less requests such as GET. The ``Date`` header is set if it is absent. In addition,
the ``Authorization`` header is signed if it is present, and for requests with bodies (such as POST), the
``Content-Digest`` header is set to the SHA256 of the request body using the format described in the
`IETF Digest Fields draft <>`_ and signed.
To add other headers to the signature, pass an array of header names in the ``covered_component_ids`` keyword argument.
See the `API documentation <>`_ for the full list of options and

Verifying responses
The class method ``HTTPSignatureAuth.verify()`` can be used to verify responses received back from the server:

.. code-block:: python

class MyKeyResolver:
def resolve_public_key(self, key_id):
assert key_id == 'squirrel'
return 'monorail_cat'

response = requests.get(url, auth=auth)
verify_result = HTTPSignatureAuth.verify(response,

More generally, you can reconstruct an arbitrary request using the
`Requests API <>`_ and pass it to ``verify()``:

.. code-block:: python

request = requests.Request(...) # Reconstruct the incoming request using the Requests API
prepared_request = request.prepare() # Generate a PreparedRequest
HTTPSignatureAuth.verify(prepared_request, ...)

To verify incoming requests and sign responses in the context of an HTTP server, see the
`flask-http-signature <>`_ and
`http-message-signatures <>`_ packages.

.. admonition:: See what is signed

It is important to understand and follow the best practice rule of "See what is signed" when verifying HTTP message
signatures. The gist of this rule is: if your application neglects to verify that the information it trusts is
what was actually signed, the attacker can supply a valid signature but point you to malicious data that wasn't signed
by that signature. Failure to follow this rule can lead to vulnerability against signature wrapping and substitution

In requests-http-signature, you can ensure that the information signed is what you expect to be signed by only trusting
the data returned by the ``verify()`` method::

verify_result = HTTPSignatureAuth.verify(message, ...)

See the `API documentation <>`_ for full details.

Asymmetric key algorithms
To sign or verify messages with an asymmetric key algorithm, set the ``signature_algorithm`` keyword argument to
``algorithms.ED25519``, ``algorithms.ECDSA_P256_SHA256``, ``algorithms.RSA_V1_5_SHA256``, or

For asymmetric key algorithms, you can supply the private key as the ``key`` parameter to the ``HTTPSignatureAuth()``
constructor as bytes in the PEM format, or configure the key resolver as follows:

.. code-block:: python

with open('key.pem', 'rb') as fh:
auth = HTTPSignatureAuth(signature_algorithm=algorithms.RSA_V1_5_SHA256,,
requests.get(url, auth=auth)

class MyKeyResolver:
def resolve_public_key(self, key_id: str):
return public_key_pem_bytes[key_id]

def resolve_private_key(self, key_id: str):
return private_key_pem_bytes[key_id]

auth = HTTPSignatureAuth(signature_algorithm=algorithms.RSA_V1_5_SHA256,,
requests.get(url, auth=auth)

Digest algorithms
To generate a Content-Digest header using SHA-512 instead of the default SHA-256, subclass ``HTTPSignatureAuth`` as

class MySigner(HTTPSignatureAuth):
signing_content_digest_algorithm = "sha-512"

* `Project home page (GitHub) <>`_
* `Package documentation <>`_
* `Package distribution (PyPI) <>`_
* `Change log <>`_
* `http-message-signatures <>`_ - a dependency of this library that
handles much of the implementation
* `IETF HTTP Signatures draft <>`_

Please report bugs, issues, feature requests, etc. on `GitHub <>`_.

Licensed under the terms of the `Apache License, Version 2.0 <>`_.