Skip to content

Commit

Permalink
import jwt == 0.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
yosida95 committed Jan 31, 2017
1 parent aced4b6 commit aba9787
Show file tree
Hide file tree
Showing 18 changed files with 790 additions and 1,140 deletions.
61 changes: 50 additions & 11 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,30 +1,40 @@
# Created by http://www.gitignore.io

# Created by https://www.gitignore.io/api/python

### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
env/
bin/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt
Expand All @@ -33,26 +43,55 @@ pip-delete-this-directory.txt
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/

# Translations
*.mo

# Mr Developer
.mr.developer.cfg
.project
.pydevproject

# Rope
.ropeproject
*.pot

# Django stuff:
*.log
*.pot
local_settings.py

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# dotenv
.env

# virtualenv
.venv/
venv/
ENV/

# Spyder project settings
.spyderproject

# Rope project settings
.ropeproject

# End of https://www.gitignore.io/api/python
11 changes: 3 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
language: python
env:
matrix:
- TOXENV=py27
- TOXENV=py33
- TOXENV=py34
- TOXENV=coverage
- TOXENV=py35
install:
- pip install tox
- if test "$TOXENV" = coverage; then pip install coveralls; fi
- if test "$TOXENV" = py35; then pip install coveralls; fi
script:
- tox
after_success:
- if test "$TOXENV" = coverage; then coveralls; fi
notifications:
slack:
- secure: NdVJltk6cQOjZHD0/8qzbdjRWYXgNhAkmoMuG8u0Y//9T7XY+BtNpOIDjInhU4/LZAP+kCl2uZuDo7ueU50+J+PKL1t7BhwWwn2al8S93M3KsiHvN8CrQkheQ2gpOTV70CaGO1sS1eokdVr7/ss557WIhkkFfZPv0hWkA+bhAiY=
- if test "$TOXENV" = py35; then coveralls; fi
42 changes: 40 additions & 2 deletions jwt/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,42 @@
# -*- coding: utf-8 -*-
#
# Copyright 2017 Gehirn Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import absolute_import
from jwt.jwt import *
from .jwk import (
AbstractJWKBase,
jwk_from_dict,
supported_key_types,
)
from .jwkset import JWKSet
from .jws import (
AbstractSigningAlgorithm,
supported_signing_algorithms,
)
from .jwt import JWT


__all__ = [
# .jwk
'AbstractJWKBase',
'jwk_from_dict',
'supported_key_types',
# .jwkset
'JWKSet',
# .jws
'AbstractSigningAlgorithm',
'supported_signing_algorithms',
# .jwt
'JWT',
]
36 changes: 30 additions & 6 deletions jwt/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,32 @@
# -*- coding: utf-8 -*-
#
# Copyright 2017 Gehirn Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

JWTException = type('JWTException', (Exception, ), {})
MalformedJWT = type('MalformedJWT', (JWTException, ), {})
KeyNotFound = type('KeyNotFound', (JWTException, ), {})
InvalidKeyType = type('InvalidKeyType', (JWTException, ), {})
UnsupportedKeyType = type('UnsupportedKeyType', (JWTException, ), {})
UnsupportedAlgorithm = type('UnsupportedAlgorithm', (JWTException, ), {})

class JWTException(Exception):
"""
common base class for all exceptions used in python-jwt
"""


MalformedJWKError = type('MalformedJWKError', (JWTException, ), {})
UnsupportedKeyTypeError = type('UnsupportedKeyTypeError', (JWTException, ), {})

InvalidKeyTypeError = type('InvalidKeyTypeError', (JWTException, ), {})

JWSEncodeError = type('JWSEncodeError', (JWTException, ), {})
JWSDecodeError = type('JWSDecodeError', (JWTException, ), {})
JWTEncodeError = type('JWTEncodeError', (JWTException, ), {})
JWTDecodeError = type('JWTDecodeError', (JWTException, ), {})
27 changes: 0 additions & 27 deletions jwt/interfaces.py

This file was deleted.

117 changes: 117 additions & 0 deletions jwt/jwa.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# -*- coding: utf-8 -*-
#
# Copyright 2017 Gehirn Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import hashlib
import hmac

from cryptography.hazmat.primitives.hashes import (
SHA256,
SHA384,
SHA512,
)

from .exceptions import InvalidKeyTypeError
from .jwk import AbstractJWKBase


class AbstractSigningAlgorithm:

def sign(self, message: bytes, key: AbstractJWKBase) -> bytes:
raise NotImplementedError()

def verify(self, message: bytes, key: AbstractJWKBase,
signature: bytes) -> bool:
raise NotImplementedError()


class NoneSigningAlgorithm(AbstractSigningAlgorithm):

def sign(self, message: bytes, key: AbstractJWKBase) -> bytes:
return b''

def verify(self, message: bytes, key: AbstractJWKBase,
signature: bytes) -> bool:
return signature == b''


class HMACAlgorithm(AbstractSigningAlgorithm):

def __init__(self, hash_fun: object) -> None:
self.hash_fun = hash_fun

def _check_key(self, key: AbstractJWKBase) -> None:
if key.get_kty() != 'oct':
raise InvalidKeyTypeError((
'an octet key is required, but passed is {}'
).format(key.get_kty()))

def _sign(self, message: bytes, key: bytes) -> bytes:
return hmac.new(key, message, self.hash_fun).digest()

def sign(self, message: bytes, key: AbstractJWKBase) -> bytes:
self._check_key(key)
return key.sign(message, signer=self._sign)

def verify(self, message: bytes, key: AbstractJWKBase,
signature: bytes) -> bool:
self._check_key(key)
return key.verify(message, signature, self._sign)


HS256 = HMACAlgorithm(hashlib.sha256)
HS384 = HMACAlgorithm(hashlib.sha384)
HS512 = HMACAlgorithm(hashlib.sha512)


class RSAAlgorithm(AbstractSigningAlgorithm):

def __init__(self, hash_fun: object) -> None:
self.hash_fun = hash_fun

def _check_key(self, key: AbstractJWKBase, must_sign_key=False) -> None:
if key.get_kty() != 'RSA':
raise InvalidKeyTypeError((
'a RSA key is required, but passed is {}'
).format(key.get_kty()))
if must_sign_key and not key.is_sign_key():
raise InvalidKeyTypeError(
'a RSA private key is required, but passed is RSA public key')

def sign(self, message: bytes, key: AbstractJWKBase) -> bytes:
self._check_key(key, must_sign_key=True)
return key.sign(message, hash_fun=self.hash_fun)

def verify(self, message: bytes, key: AbstractJWKBase,
signature: bytes) -> bool:
self._check_key(key)
return key.verify(message, signature, hash_fun=self.hash_fun)


RS256 = RSAAlgorithm(SHA256)
RS384 = RSAAlgorithm(SHA384)
RS512 = RSAAlgorithm(SHA512)


def supported_signing_algorithms():
return {
'none': NoneSigningAlgorithm(),
'HS256': HS256,
'HS384': HS384,
'HS512': HS512,
'RS256': RS256,
'RS384': RS384,
'RS512': RS512,
}
Loading

0 comments on commit aba9787

Please sign in to comment.