1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
httpsig
=======
.. image:: https://travis-ci.org/ahknight/httpsig.svg?branch=master
:target: https://travis-ci.org/ahknight/httpsig
.. image:: https://travis-ci.org/ahknight/httpsig.svg?branch=develop
:target: https://travis-ci.org/ahknight/httpsig
Sign HTTP requests with secure signatures according to the IETF HTTP Signatures specification (`Draft 8`_). This is a fork of the original module_ to fully support both RSA and HMAC schemes as well as unit test both schemes to prove they work. It's being used in production and is actively-developed.
See the original project_, original Python module_, original spec_, and `current IETF draft`_ for more details on the signing scheme.
.. _project: https://github.com/joyent/node-http-signature
.. _module: https://github.com/zzsnzmn/py-http-signature
.. _spec: https://github.com/joyent/node-http-signature/blob/master/http_signing.md
.. _`current IETF draft`: https://datatracker.ietf.org/doc/draft-cavage-http-signatures/
.. _`Draft 8`: http://tools.ietf.org/html/draft-cavage-http-signatures-08
Requirements
------------
* Python 2.7, 3.4-3.7
* PyCryptodome_
Optional:
* requests_
.. _PyCryptodome: https://pypi.python.org/pypi/pycryptodome
.. _requests: https://pypi.python.org/pypi/requests
For testing:
* tox
* pyenv (optional, handy way to access multiple versions)
$ for VERS in 2.7.15 3.4.9 3.5.6 3.6.7 3.7.1; do pyenv install -s $VERS; done
Usage
-----
Real documentation is forthcoming, but for now this should get you started.
For simple raw signing:
.. code:: python
import httpsig
secret = open('rsa_private.pem', 'rb').read()
sig_maker = httpsig.Signer(secret=secret, algorithm='rsa-sha256')
sig_maker.sign('hello world!')
For general use with web frameworks:
.. code:: python
import httpsig
key_id = "Some Key ID"
secret = b'some big secret'
hs = httpsig.HeaderSigner(key_id, secret, algorithm="hmac-sha256", headers=['(request-target)', 'host', 'date'])
signed_headers_dict = hs.sign({"Date": "Tue, 01 Jan 2014 01:01:01 GMT", "Host": "example.com"}, method="GET", path="/api/1/object/1")
For use with requests:
.. code:: python
import json
import requests
from httpsig.requests_auth import HTTPSignatureAuth
secret = open('rsa_private.pem', 'rb').read()
auth = HTTPSignatureAuth(key_id='Test', secret=secret)
z = requests.get('https://api.example.com/path/to/endpoint',
auth=auth, headers={'X-Api-Version': '~6.5'})
Class initialization parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Note that keys and secrets should be bytes objects. At attempt will be made to convert them, but if that fails then exceptions will be thrown.
.. code:: python
httpsig.Signer(secret, algorithm='rsa-sha256')
``secret``, in the case of an RSA signature, is a string containing private RSA pem. In the case of HMAC, it is a secret password.
``algorithm`` is one of the six allowed signatures: ``rsa-sha1``, ``rsa-sha256``, ``rsa-sha512``, ``hmac-sha1``, ``hmac-sha256``,
``hmac-sha512``.
.. code:: python
httpsig.requests_auth.HTTPSignatureAuth(key_id, secret, algorithm='rsa-sha256', headers=None)
``key_id`` is the label by which the server system knows your RSA signature or password.
``headers`` is the list of HTTP headers that are concatenated and used as signing objects. By default it is the specification's minimum, the ``Date`` HTTP header.
``secret`` and ``algorithm`` are as above.
Tests
-----
To run tests::
python setup.py test
or::
tox
Known Limitations
-----------------
1. Multiple values for the same header are not supported. New headers with the same name will overwrite the previous header. It might be possible to replace the CaseInsensitiveDict with the collection that the email package uses for headers to overcome this limitation.
2. Keyfiles with passwords are not supported. There has been zero vocal demand for this so if you would like it, a PR would be a good way to get it in.
3. Draft 2 added support for ecdsa-sha256. This is available in PyCryptodome but has not been added to httpsig. PRs welcome.
License
-------
Both this module and the original module_ are licensed under the MIT license.
|