This repository has been archived by the owner on Nov 13, 2023. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TODO: Figure out Python packing mess. Might use Bento.
- Loading branch information
1 parent
24c8004
commit af596e0
Showing
68 changed files
with
6,527 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[run] | ||
branch = True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
*.pyc | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
Copyright (c) 2013 David Halls <https://github.com/davedoesdev/> | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is furnished | ||
to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
|
||
export PYTHONPATH=. | ||
PYVOWS = ./test/pyvows.sh | ||
|
||
all: lint test | ||
|
||
docs: build_docs | ||
|
||
build_docs: | ||
cd docs && make html | ||
|
||
lint: | ||
pylint jwt test bench | ||
|
||
test: run_test | ||
|
||
run_test: | ||
$(PYVOWS) test | ||
|
||
coverage: run_coverage | ||
|
||
run_coverage: | ||
$(PYVOWS) --cover --cover-package jwt --cover-report coverage/coverage.xml test | ||
|
||
bench: run_bench | ||
|
||
run_bench: | ||
for b in ./bench/*_bench.py; do $$b; done | ||
|
||
bench_gfm: | ||
for b in ./bench/*_bench.py; do $$b --gfm; done | ||
|
||
dev_deps: | ||
mkdir -p node_modules && npm install jsjws sinon |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
# python-jwt [![Build Status](https://travis-ci.org/davedoesdev/python-jwt.png)](https://travis-ci.org/davedoesdev/python-jwt) [![Coverage Status](https://coveralls.io/repos/davedoesdev/python-jwt/badge.png?branch=master)](https://coveralls.io/r/davedoesdev/python-jwt?branch=master) [![PyPI version](https://badge.fury.io/py/jwt.png)](http://badge.fury.io/py/jwt) | ||
|
||
Module for generating and verifying JSON Web Tokens. | ||
|
||
- Uses [jws](https://github.com/brianloveswords/python-jws) to do the heavy lifting. | ||
- Supports [__RS256__, __RS384__, __RS512__](http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-14#section-3.3), [__PS256__, __PS384__, __PS512__](http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-14#section-3.5), [__HS256__, __HS384__ and __HS512__](http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-14#section-3.2) signature algorithms. | ||
- Unit tests, including tests for interoperability with [node-jsjws](https://github.com/davedoesdev/node-jsjws). | ||
|
||
Example: | ||
|
||
```python | ||
import jwt, Crypto.PublicKey.RSA as RSA, datetime | ||
key = RSA.generate(2048) | ||
payload = { 'foo': 'bar', 'wup': 90 }; | ||
token = jwt.generate_jwt(payload, key, 'PS256', datetime.timedelta(minutes=5)) | ||
header, claims = jwt.verify_jwt(token, key) | ||
for k in payload: assert claims[k] == payload[k] | ||
``` | ||
|
||
The API is described [here](docs/_build/html/index.html). | ||
|
||
## Installation | ||
|
||
```shell | ||
pip install jwt | ||
``` | ||
|
||
## Another Example | ||
|
||
You can read and write keys from and to [PEM-format](http://www.openssl.org/docs/crypto/pem.html) strings: | ||
|
||
```python | ||
import jwt, Crypto.PublicKey.RSA as RSA, datetime | ||
key = RSA.generate(2048) | ||
priv_pem = key.exportKey() | ||
pub_pem = key.publickey().exportKey() | ||
payload = { 'foo': 'bar', 'wup': 90 }; | ||
priv_key = RSA.importKey(priv_pem) | ||
pub_key = RSA.importKey(pub_pem) | ||
token = jwt.generate_jwt(payload, priv_key, 'RS256', datetime.timedelta(minutes=5)) | ||
header, claims = jwt.verify_jwt(token, pub_key) | ||
for k in payload: assert claims[k] == payload[k] | ||
``` | ||
|
||
## Licence | ||
|
||
[MIT](LICENCE) | ||
|
||
## Tests | ||
|
||
```shell | ||
make test | ||
``` | ||
|
||
## Lint | ||
|
||
```shell | ||
make lint | ||
``` | ||
|
||
## Code Coverage | ||
|
||
```shell | ||
make coverage | ||
``` | ||
|
||
[coverage.py](http://nedbatchelder.com/code/coverage/) results are available [here](http://htmlpreview.github.io/?https://github.com/davedoesdev/python-jwt/blob/master/coverage/html/index.html). | ||
|
||
Coveralls page is [here](https://coveralls.io/r/davedoesdev/python-jwt). | ||
|
||
## Benchmarks | ||
|
||
```shell | ||
make bench | ||
``` | ||
|
||
Here are some results on a laptop with an Intel Core i5-3210M 2.5Ghz CPU and 6Gb RAM running Ubuntu 13.04. | ||
|
||
Generate Key|user (ns)|sys (ns)|real (ns) | ||
:--|--:|--:|--: | ||
RSA|152,700,000|300,000|152,906,095 | ||
|
||
Generate Token|user (ns)|sys (ns)|real (ns) | ||
:--|--:|--:|--: | ||
HS256|140,000|10,000|157,202 | ||
HS384|160,000|10,000|156,403 | ||
HS512|139,999|20,000|153,212 | ||
PS256|3,159,999|49,999|3,218,649 | ||
PS384|3,170,000|10,000|3,176,899 | ||
PS512|3,120,000|9,999|3,141,219 | ||
RS256|3,070,000|20,000|3,094,644 | ||
RS384|3,090,000|0|3,092,471 | ||
RS512|3,079,999|20,000|3,095,314 | ||
|
||
Load Key|user (ns)|sys (ns)|real (ns) | ||
:--|--:|--:|--: | ||
RSA|811,000|0|810,139 | ||
|
||
Verify Token|user (ns)|sys (ns)|real (ns) | ||
:--|--:|--:|--: | ||
HS256|140,000|0|129,947 | ||
HS384|130,000|0|130,161 | ||
HS512|119,999|0|128,850 | ||
PS256|780,000|10,000|775,609 | ||
PS384|759,999|0|752,933 | ||
PS512|739,999|0|738,118 | ||
RS256|700,000|0|719,365 | ||
RS384|719,999|0|721,524 | ||
RS512|730,000|0|719,706 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
""" Keep pylint happy """ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#!/usr/bin/env python | ||
|
||
""" Benchmark generating an RSA key """ | ||
|
||
import Crypto.PublicKey.RSA as RSA | ||
from unitbench import Benchmark | ||
from bench.reporter import Reporter | ||
|
||
class GenerateKeyBenchmark(Benchmark): | ||
""" Generate key benchmark """ | ||
|
||
def input(self): | ||
""" Name of benchmark """ | ||
return ["Generate Key"] | ||
|
||
def repeats(self): | ||
""" Iterations """ | ||
return 100 | ||
|
||
def bench_RSA(self): | ||
""" Generate key """ | ||
RSA.generate(2048) | ||
|
||
if __name__ == "__main__": | ||
#pylint: disable=W0402 | ||
import string | ||
string.capwords = lambda x: x | ||
GenerateKeyBenchmark().run(reporter=Reporter()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#!/usr/bin/env python | ||
|
||
""" Benchmark generating a JWT """ | ||
|
||
from datetime import timedelta | ||
from unitbench import Benchmark | ||
from test.fixtures import payload, priv_keys, priv_key, algs | ||
from bench.reporter import Reporter | ||
import jwt | ||
|
||
class GenerateTokenBenchmark(Benchmark): | ||
""" Generate JWT benchmark """ | ||
|
||
def input(self): | ||
""" Nme of benchmark """ | ||
return ["Generate Token"] | ||
|
||
def repeats(self): | ||
""" Iterations """ | ||
return 1000 | ||
|
||
#pylint: disable=W0621 | ||
def make_bench_generate_token(alg): | ||
""" Return function which will generate token for particular algorithm """ | ||
def f(_): | ||
""" Generate token """ | ||
privk = priv_keys[alg].get('default', priv_key) | ||
jwt.generate_jwt(payload, privk, alg, timedelta(seconds=5)) | ||
return f | ||
|
||
for alg in algs: | ||
name = 'bench_' + alg | ||
f = make_bench_generate_token(alg) | ||
f.__name__ = name | ||
setattr(GenerateTokenBenchmark, name, f) | ||
|
||
if __name__ == "__main__": | ||
#pylint: disable=W0402 | ||
import string | ||
string.capwords = lambda x: x | ||
GenerateTokenBenchmark().run(reporter=Reporter()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#!/usr/bin/env python | ||
|
||
""" Benchmark loading an RSA key from a PEM string """ | ||
|
||
import Crypto.PublicKey.RSA as RSA | ||
from unitbench import Benchmark | ||
from test.fixtures import priv_pem | ||
from bench.reporter import Reporter | ||
|
||
class LoadKeyBenchmark(Benchmark): | ||
""" Load key benchmark """ | ||
|
||
def input(self): | ||
""" Name of benchmark """ | ||
return ["Load Key"] | ||
|
||
def repeats(self): | ||
""" Iterations """ | ||
return 10000 | ||
|
||
def bench_RSA(self): | ||
""" Import key """ | ||
RSA.importKey(priv_pem) | ||
|
||
if __name__ == "__main__": | ||
#pylint: disable=W0402 | ||
import string | ||
string.capwords = lambda x: x | ||
LoadKeyBenchmark().run(reporter=Reporter()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
""" Custom reporter to generate Github-flavoured markdown tables """ | ||
|
||
import sys | ||
import unitbench | ||
import argparse | ||
|
||
parser = argparse.ArgumentParser() | ||
parser.add_argument('--gfm', dest='gfm', action='store_true') | ||
gfm = parser.parse_args().gfm | ||
|
||
class Reporter(unitbench.Reporter): | ||
""" Custom reporter """ | ||
|
||
def __init__(self, output_stream=sys.stdout): | ||
self.stream = output_stream | ||
|
||
def write_results(self, value, results): | ||
if gfm: | ||
self.stream.write("{0}|{1}|{2}|{3}\n".format(value, "user (ns)", "sys (ns)", "real (ns)")) | ||
self.stream.write(":--|--:|--:|--:\n") | ||
for r in results: | ||
if (hasattr(r, "user_mean") and | ||
hasattr(r, "system_mean") and hasattr(r, "wall_mean")): | ||
self.stream.write("{0}|{1:,}|{2:,}|{3:,}\n".format(r.name, | ||
long(r.user_mean * 10**9), | ||
long(r.system_mean * 10**9), | ||
long(r.wall_mean * 10**9))) | ||
else: | ||
self.stream.write("{0:<20}{1:>15}{2:>15}{3:>15}\n".format(value, "user (ns)", "sys (ns)", "real (ns)")) | ||
self.stream.write("=" * 65 + "\n") | ||
for r in results: | ||
if (hasattr(r, "user_mean") and | ||
hasattr(r, "system_mean") and hasattr(r, "wall_mean")): | ||
self.stream.write("{0:<20} {1:>14,} {2:>14,} {3:>14,}\n".format(r.name, | ||
long(r.user_mean * 10**9), | ||
long(r.system_mean * 10**9), | ||
long(r.wall_mean * 10**9))) | ||
self.stream.write("\n") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#!/usr/bin/env python | ||
|
||
""" Benchmark verifying a JWT """ | ||
|
||
from datetime import timedelta | ||
from unitbench import Benchmark | ||
from test.fixtures import payload, priv_keys, priv_key, pub_keys, pub_key, algs | ||
from bench.reporter import Reporter | ||
import jwt | ||
|
||
class VerifyTokenBenchmark(Benchmark): | ||
""" Verify JWT benchmark """ | ||
|
||
def input(self): | ||
""" Name of benchmark """ | ||
return ["Verify Token"] | ||
|
||
def repeats(self): | ||
""" Iterations """ | ||
return 1000 | ||
|
||
#pylint: disable=W0621 | ||
def make_bench_verify_token(alg): | ||
""" Return function which will generate token for particular algorith """ | ||
privk = priv_keys[alg].get('default', priv_key) | ||
token = jwt.generate_jwt(payload, privk, alg, timedelta(days=1)) | ||
def f(_): | ||
""" Verify token """ | ||
pubk = pub_keys[alg].get('default', pub_key) | ||
jwt.verify_jwt(token, pubk) | ||
return f | ||
|
||
for alg in algs: | ||
name = 'bench_' + alg | ||
f = make_bench_verify_token(alg) | ||
f.__name__ = name | ||
setattr(VerifyTokenBenchmark, name, f) | ||
|
||
if __name__ == "__main__": | ||
#pylint: disable=W0402 | ||
import string | ||
string.capwords = lambda x: x | ||
VerifyTokenBenchmark().run(reporter=Reporter()) |
Oops, something went wrong.