summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Padilla <jpadilla@webapplicate.com>2015-03-17 10:08:44 -0400
committerJosé Padilla <jpadilla@webapplicate.com>2015-03-17 10:08:44 -0400
commitd47163117bef52392f314406ad0a4177e2a65e16 (patch)
tree7920c174502cad2d6d8721a3925736738fd33d94
parent492e96f91da493924fd1e6f279054935d5ad69e4 (diff)
parent7c4e96b3a56e7d8b8a4b05b086639c1e2ac25cca (diff)
downloadpyjwt-d47163117bef52392f314406ad0a4177e2a65e16.tar.gz
Merge pull request #103 from mark-adams/contrib-algorithms
Back from the dead: PyCrypto and ECDSA
-rw-r--r--.travis.yml4
-rw-r--r--jwt/algorithms.py33
-rw-r--r--jwt/contrib/__init__.py0
-rw-r--r--jwt/contrib/algorithms/__init__.py0
-rw-r--r--jwt/contrib/algorithms/py_ecdsa.py60
-rw-r--r--jwt/contrib/algorithms/pycrypto.py47
-rw-r--r--tests/contrib/__init__.py0
-rw-r--r--tests/contrib/test_algorithms.py193
-rw-r--r--tests/test_algorithms.py44
-rw-r--r--tests/utils.py7
-rw-r--r--tox.ini25
11 files changed, 376 insertions, 37 deletions
diff --git a/.travis.yml b/.travis.yml
index 62aee8e..6dbb1b0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,14 +1,16 @@
language: python
sudo: false
env:
+ - TOXENV=pep8
- TOXENV=py26
- TOXENV=py27
- TOXENV=py32
- TOXENV=py33
- TOXENV=py34
- - TOXENV=pep8
- TOXENV=py34-nocrypto
- TOXENV=py27-nocrypto
+ - TOXENV=py34-contrib-crypto
+ - TOXENV=py27-contrib-crypto
install:
- pip install tox coveralls
script:
diff --git a/jwt/algorithms.py b/jwt/algorithms.py
index d347dcc..720d675 100644
--- a/jwt/algorithms.py
+++ b/jwt/algorithms.py
@@ -23,18 +23,18 @@ def _register_default_algorithms():
Registers the algorithms that are implemented by the library.
"""
register_algorithm('none', NoneAlgorithm())
- register_algorithm('HS256', HMACAlgorithm(hashlib.sha256))
- register_algorithm('HS384', HMACAlgorithm(hashlib.sha384))
- register_algorithm('HS512', HMACAlgorithm(hashlib.sha512))
+ register_algorithm('HS256', HMACAlgorithm(HMACAlgorithm.SHA256))
+ register_algorithm('HS384', HMACAlgorithm(HMACAlgorithm.SHA384))
+ register_algorithm('HS512', HMACAlgorithm(HMACAlgorithm.SHA512))
if has_crypto:
- register_algorithm('RS256', RSAAlgorithm(hashes.SHA256()))
- register_algorithm('RS384', RSAAlgorithm(hashes.SHA384()))
- register_algorithm('RS512', RSAAlgorithm(hashes.SHA512()))
+ register_algorithm('RS256', RSAAlgorithm(RSAAlgorithm.SHA256))
+ register_algorithm('RS384', RSAAlgorithm(RSAAlgorithm.SHA384))
+ register_algorithm('RS512', RSAAlgorithm(RSAAlgorithm.SHA512))
- register_algorithm('ES256', ECAlgorithm(hashes.SHA256()))
- register_algorithm('ES384', ECAlgorithm(hashes.SHA384()))
- register_algorithm('ES512', ECAlgorithm(hashes.SHA512()))
+ register_algorithm('ES256', ECAlgorithm(ECAlgorithm.SHA256))
+ register_algorithm('ES384', ECAlgorithm(ECAlgorithm.SHA384))
+ register_algorithm('ES512', ECAlgorithm(ECAlgorithm.SHA512))
class Algorithm(object):
@@ -83,6 +83,10 @@ class HMACAlgorithm(Algorithm):
Performs signing and verification operations using HMAC
and the specified hash function.
"""
+ SHA256 = hashlib.sha256
+ SHA384 = hashlib.sha384
+ SHA512 = hashlib.sha512
+
def __init__(self, hash_alg):
self.hash_alg = hash_alg
@@ -108,9 +112,12 @@ if has_crypto:
Performs signing and verification operations using
RSASSA-PKCS-v1_5 and the specified hash function.
"""
+ SHA256 = hashes.SHA256
+ SHA384 = hashes.SHA384
+ SHA512 = hashes.SHA512
def __init__(self, hash_alg):
- self.hash_alg = hash_alg
+ self.hash_alg = hash_alg()
def prepare_key(self, key):
if isinstance(key, interfaces.RSAPrivateKey) or \
@@ -162,8 +169,12 @@ if has_crypto:
Performs signing and verification operations using
ECDSA and the specified hash function
"""
+ SHA256 = hashes.SHA256
+ SHA384 = hashes.SHA384
+ SHA512 = hashes.SHA512
+
def __init__(self, hash_alg):
- self.hash_alg = hash_alg
+ self.hash_alg = hash_alg()
def prepare_key(self, key):
if isinstance(key, interfaces.EllipticCurvePrivateKey) or \
diff --git a/jwt/contrib/__init__.py b/jwt/contrib/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/jwt/contrib/__init__.py
diff --git a/jwt/contrib/algorithms/__init__.py b/jwt/contrib/algorithms/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/jwt/contrib/algorithms/__init__.py
diff --git a/jwt/contrib/algorithms/py_ecdsa.py b/jwt/contrib/algorithms/py_ecdsa.py
new file mode 100644
index 0000000..dea2710
--- /dev/null
+++ b/jwt/contrib/algorithms/py_ecdsa.py
@@ -0,0 +1,60 @@
+# Note: This file is named py_ecdsa.py because import behavior in Python 2
+# would cause ecdsa.py to squash the ecdsa library that it depends upon.
+
+import hashlib
+
+import ecdsa
+
+from jwt.algorithms import Algorithm
+from jwt.compat import string_types, text_type
+
+
+class ECAlgorithm(Algorithm):
+ """
+ Performs signing and verification operations using
+ ECDSA and the specified hash function
+
+ This class requires the ecdsa package to be installed.
+
+ This is based off of the implementation in PyJWT 0.3.2
+ """
+ SHA256 = hashlib.sha256
+ SHA384 = hashlib.sha384
+ SHA512 = hashlib.sha512
+
+ def __init__(self, hash_alg):
+ self.hash_alg = hash_alg
+
+ def prepare_key(self, key):
+
+ if isinstance(key, ecdsa.SigningKey) or \
+ isinstance(key, ecdsa.VerifyingKey):
+ return key
+
+ if isinstance(key, string_types):
+ if isinstance(key, text_type):
+ key = key.encode('utf-8')
+
+ # Attempt to load key. We don't know if it's
+ # a Signing Key or a Verifying Key, so we try
+ # the Verifying Key first.
+ try:
+ key = ecdsa.VerifyingKey.from_pem(key)
+ except ecdsa.der.UnexpectedDER:
+ key = ecdsa.SigningKey.from_pem(key)
+
+ else:
+ raise TypeError('Expecting a PEM-formatted key.')
+
+ return key
+
+ def sign(self, msg, key):
+ return key.sign(msg, hashfunc=self.hash_alg,
+ sigencode=ecdsa.util.sigencode_der)
+
+ def verify(self, msg, key, sig):
+ try:
+ return key.verify(sig, msg, hashfunc=self.hash_alg,
+ sigdecode=ecdsa.util.sigdecode_der)
+ except ecdsa.der.UnexpectedDER:
+ return False
diff --git a/jwt/contrib/algorithms/pycrypto.py b/jwt/contrib/algorithms/pycrypto.py
new file mode 100644
index 0000000..e6afaa5
--- /dev/null
+++ b/jwt/contrib/algorithms/pycrypto.py
@@ -0,0 +1,47 @@
+import Crypto.Hash.SHA256
+import Crypto.Hash.SHA384
+import Crypto.Hash.SHA512
+
+from Crypto.PublicKey import RSA
+from Crypto.Signature import PKCS1_v1_5
+
+from jwt.algorithms import Algorithm
+from jwt.compat import string_types, text_type
+
+
+class RSAAlgorithm(Algorithm):
+ """
+ Performs signing and verification operations using
+ RSASSA-PKCS-v1_5 and the specified hash function.
+
+ This class requires PyCrypto package to be installed.
+
+ This is based off of the implementation in PyJWT 0.3.2
+ """
+ SHA256 = Crypto.Hash.SHA256
+ SHA384 = Crypto.Hash.SHA384
+ SHA512 = Crypto.Hash.SHA512
+
+ def __init__(self, hash_alg):
+ self.hash_alg = hash_alg
+
+ def prepare_key(self, key):
+
+ if isinstance(key, RSA._RSAobj):
+ return key
+
+ if isinstance(key, string_types):
+ if isinstance(key, text_type):
+ key = key.encode('utf-8')
+
+ key = RSA.importKey(key)
+ else:
+ raise TypeError('Expecting a PEM- or RSA-formatted key.')
+
+ return key
+
+ def sign(self, msg, key):
+ return PKCS1_v1_5.new(key).sign(self.hash_alg.new(msg))
+
+ def verify(self, msg, key, sig):
+ return PKCS1_v1_5.new(key).verify(self.hash_alg.new(msg), sig)
diff --git a/tests/contrib/__init__.py b/tests/contrib/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/contrib/__init__.py
diff --git a/tests/contrib/test_algorithms.py b/tests/contrib/test_algorithms.py
new file mode 100644
index 0000000..2b156f8
--- /dev/null
+++ b/tests/contrib/test_algorithms.py
@@ -0,0 +1,193 @@
+import base64
+
+from ..compat import unittest
+from ..utils import ensure_bytes, ensure_unicode, key_path
+
+try:
+ from jwt.contrib.algorithms.pycrypto import RSAAlgorithm
+ has_pycrypto = True
+except ImportError:
+ has_pycrypto = False
+
+try:
+ from jwt.contrib.algorithms.py_ecdsa import ECAlgorithm
+ has_ecdsa = True
+except ImportError:
+ has_ecdsa = False
+
+
+@unittest.skipIf(not has_pycrypto, 'Not supported without PyCrypto library')
+class TestPycryptoAlgorithms(unittest.TestCase):
+ def setUp(self): # noqa
+ pass
+
+ def test_rsa_should_parse_pem_public_key(self):
+ algo = RSAAlgorithm(RSAAlgorithm.SHA256)
+
+ with open(key_path('testkey2_rsa.pub.pem'), 'r') as pem_key:
+ algo.prepare_key(pem_key.read())
+
+ def test_rsa_should_accept_unicode_key(self):
+ algo = RSAAlgorithm(RSAAlgorithm.SHA256)
+
+ with open(key_path('testkey_rsa'), 'r') as rsa_key:
+ algo.prepare_key(ensure_unicode(rsa_key.read()))
+
+ def test_rsa_should_reject_non_string_key(self):
+ algo = RSAAlgorithm(RSAAlgorithm.SHA256)
+
+ with self.assertRaises(TypeError):
+ algo.prepare_key(None)
+
+ def test_rsa_sign_should_generate_correct_signature_value(self):
+ algo = RSAAlgorithm(RSAAlgorithm.SHA256)
+
+ jwt_message = ensure_bytes('Hello World!')
+
+ expected_sig = base64.b64decode(ensure_bytes(
+ 'yS6zk9DBkuGTtcBzLUzSpo9gGJxJFOGvUqN01iLhWHrzBQ9ZEz3+Ae38AXp'
+ '10RWwscp42ySC85Z6zoN67yGkLNWnfmCZSEv+xqELGEvBJvciOKsrhiObUl'
+ '2mveSc1oeO/2ujkGDkkkJ2epn0YliacVjZF5+/uDmImUfAAj8lzjnHlzYix'
+ 'sn5jGz1H07jYYbi9diixN8IUhXeTafwFg02IcONhum29V40Wu6O5tAKWlJX'
+ 'fHJnNUzAEUOXS0WahHVb57D30pcgIji9z923q90p5c7E2cU8V+E1qe8NdCA'
+ 'APCDzZZ9zQ/dgcMVaBrGrgimrcLbPjueOKFgSO+SSjIElKA=='))
+
+ with open(key_path('testkey_rsa'), 'r') as keyfile:
+ jwt_key = algo.prepare_key(keyfile.read())
+
+ with open(key_path('testkey_rsa.pub'), 'r') as keyfile:
+ jwt_pub_key = algo.prepare_key(keyfile.read())
+
+ algo.sign(jwt_message, jwt_key)
+ result = algo.verify(jwt_message, jwt_pub_key, expected_sig)
+ self.assertTrue(result)
+
+ def test_rsa_verify_should_return_false_if_signature_invalid(self):
+ algo = RSAAlgorithm(RSAAlgorithm.SHA256)
+
+ jwt_message = ensure_bytes('Hello World!')
+
+ jwt_sig = base64.b64decode(ensure_bytes(
+ 'yS6zk9DBkuGTtcBzLUzSpo9gGJxJFOGvUqN01iLhWHrzBQ9ZEz3+Ae38AXp'
+ '10RWwscp42ySC85Z6zoN67yGkLNWnfmCZSEv+xqELGEvBJvciOKsrhiObUl'
+ '2mveSc1oeO/2ujkGDkkkJ2epn0YliacVjZF5+/uDmImUfAAj8lzjnHlzYix'
+ 'sn5jGz1H07jYYbi9diixN8IUhXeTafwFg02IcONhum29V40Wu6O5tAKWlJX'
+ 'fHJnNUzAEUOXS0WahHVb57D30pcgIji9z923q90p5c7E2cU8V+E1qe8NdCA'
+ 'APCDzZZ9zQ/dgcMVaBrGrgimrcLbPjueOKFgSO+SSjIElKA=='))
+
+ jwt_sig += ensure_bytes('123') # Signature is now invalid
+
+ with open(key_path('testkey_rsa.pub'), 'r') as keyfile:
+ jwt_pub_key = algo.prepare_key(keyfile.read())
+
+ result = algo.verify(jwt_message, jwt_pub_key, jwt_sig)
+ self.assertFalse(result)
+
+ def test_rsa_verify_should_return_true_if_signature_valid(self):
+ algo = RSAAlgorithm(RSAAlgorithm.SHA256)
+
+ jwt_message = ensure_bytes('Hello World!')
+
+ jwt_sig = base64.b64decode(ensure_bytes(
+ 'yS6zk9DBkuGTtcBzLUzSpo9gGJxJFOGvUqN01iLhWHrzBQ9ZEz3+Ae38AXp'
+ '10RWwscp42ySC85Z6zoN67yGkLNWnfmCZSEv+xqELGEvBJvciOKsrhiObUl'
+ '2mveSc1oeO/2ujkGDkkkJ2epn0YliacVjZF5+/uDmImUfAAj8lzjnHlzYix'
+ 'sn5jGz1H07jYYbi9diixN8IUhXeTafwFg02IcONhum29V40Wu6O5tAKWlJX'
+ 'fHJnNUzAEUOXS0WahHVb57D30pcgIji9z923q90p5c7E2cU8V+E1qe8NdCA'
+ 'APCDzZZ9zQ/dgcMVaBrGrgimrcLbPjueOKFgSO+SSjIElKA=='))
+
+ with open(key_path('testkey_rsa.pub'), 'r') as keyfile:
+ jwt_pub_key = algo.prepare_key(keyfile.read())
+
+ result = algo.verify(jwt_message, jwt_pub_key, jwt_sig)
+ self.assertTrue(result)
+
+ def test_rsa_prepare_key_should_be_idempotent(self):
+ algo = RSAAlgorithm(RSAAlgorithm.SHA256)
+
+ with open(key_path('testkey_rsa.pub'), 'r') as keyfile:
+ jwt_pub_key_first = algo.prepare_key(keyfile.read())
+ jwt_pub_key_second = algo.prepare_key(jwt_pub_key_first)
+
+ self.assertEqual(jwt_pub_key_first, jwt_pub_key_second)
+
+
+@unittest.skipIf(not has_ecdsa, 'Not supported without ecdsa library')
+class TestEcdsaAlgorithms(unittest.TestCase):
+ def test_ec_should_reject_non_string_key(self):
+ algo = ECAlgorithm(ECAlgorithm.SHA256)
+
+ with self.assertRaises(TypeError):
+ algo.prepare_key(None)
+
+ def test_ec_should_accept_unicode_key(self):
+ algo = ECAlgorithm(ECAlgorithm.SHA256)
+
+ with open(key_path('testkey_ec'), 'r') as ec_key:
+ algo.prepare_key(ensure_unicode(ec_key.read()))
+
+ def test_ec_sign_should_generate_correct_signature_value(self):
+ algo = ECAlgorithm(ECAlgorithm.SHA256)
+
+ jwt_message = ensure_bytes('Hello World!')
+
+ expected_sig = base64.b64decode(ensure_bytes(
+ 'MIGIAkIB9vYz+inBL8aOTA4auYz/zVuig7TT1bQgKROIQX9YpViHkFa4DT5'
+ '5FuFKn9XzVlk90p6ldEj42DC9YecXHbC2t+cCQgCicY+8f3f/KCNtWK7cif'
+ '6vdsVwm6Lrjs0Ag6ZqCf+olN11hVt1qKBC4lXppqB1gNWEmNQaiz1z2QRyc'
+ 'zJ8hSJmbw=='))
+
+ with open(key_path('testkey_ec'), 'r') as keyfile:
+ jwt_key = algo.prepare_key(keyfile.read())
+
+ with open(key_path('testkey_ec.pub'), 'r') as keyfile:
+ jwt_pub_key = algo.prepare_key(keyfile.read())
+
+ algo.sign(jwt_message, jwt_key)
+ result = algo.verify(jwt_message, jwt_pub_key, expected_sig)
+ self.assertTrue(result)
+
+ def test_ec_verify_should_return_false_if_signature_invalid(self):
+ algo = ECAlgorithm(ECAlgorithm.SHA256)
+
+ jwt_message = ensure_bytes('Hello World!')
+
+ jwt_sig = base64.b64decode(ensure_bytes(
+ 'MIGIAkIB9vYz+inBL8aOTA4auYz/zVuig7TT1bQgKROIQX9YpViHkFa4DT5'
+ '5FuFKn9XzVlk90p6ldEj42DC9YecXHbC2t+cCQgCicY+8f3f/KCNtWK7cif'
+ '6vdsVwm6Lrjs0Ag6ZqCf+olN11hVt1qKBC4lXppqB1gNWEmNQaiz1z2QRyc'
+ 'zJ8hSJmbw=='))
+
+ jwt_sig += ensure_bytes('123') # Signature is now invalid
+
+ with open(key_path('testkey_ec.pub'), 'r') as keyfile:
+ jwt_pub_key = algo.prepare_key(keyfile.read())
+
+ result = algo.verify(jwt_message, jwt_pub_key, jwt_sig)
+ self.assertFalse(result)
+
+ def test_ec_verify_should_return_true_if_signature_valid(self):
+ algo = ECAlgorithm(ECAlgorithm.SHA256)
+
+ jwt_message = ensure_bytes('Hello World!')
+
+ jwt_sig = base64.b64decode(ensure_bytes(
+ 'MIGIAkIB9vYz+inBL8aOTA4auYz/zVuig7TT1bQgKROIQX9YpViHkFa4DT5'
+ '5FuFKn9XzVlk90p6ldEj42DC9YecXHbC2t+cCQgCicY+8f3f/KCNtWK7cif'
+ '6vdsVwm6Lrjs0Ag6ZqCf+olN11hVt1qKBC4lXppqB1gNWEmNQaiz1z2QRyc'
+ 'zJ8hSJmbw=='))
+
+ with open(key_path('testkey_ec.pub'), 'r') as keyfile:
+ jwt_pub_key = algo.prepare_key(keyfile.read())
+
+ result = algo.verify(jwt_message, jwt_pub_key, jwt_sig)
+ self.assertTrue(result)
+
+ def test_ec_prepare_key_should_be_idempotent(self):
+ algo = ECAlgorithm(ECAlgorithm.SHA256)
+
+ with open(key_path('testkey_ec.pub'), 'r') as keyfile:
+ jwt_pub_key_first = algo.prepare_key(keyfile.read())
+ jwt_pub_key_second = algo.prepare_key(jwt_pub_key_first)
+
+ self.assertEqual(jwt_pub_key_first, jwt_pub_key_second)
diff --git a/tests/test_algorithms.py b/tests/test_algorithms.py
index 73ebb05..0fafc4d 100644
--- a/tests/test_algorithms.py
+++ b/tests/test_algorithms.py
@@ -1,13 +1,11 @@
import base64
-import hashlib
from jwt.algorithms import Algorithm, HMACAlgorithm
from .compat import unittest
-from .utils import ensure_bytes, ensure_unicode
+from .utils import ensure_bytes, ensure_unicode, key_path
try:
- from cryptography.hazmat.primitives import hashes
from jwt.algorithms import RSAAlgorithm, ECAlgorithm
has_crypto = True
@@ -38,7 +36,7 @@ class TestAlgorithms(unittest.TestCase):
algo.verify('message', 'key', 'signature')
def test_hmac_should_reject_nonstring_key(self):
- algo = HMACAlgorithm(hashlib.sha256())
+ algo = HMACAlgorithm(HMACAlgorithm.SHA256)
with self.assertRaises(TypeError) as context:
algo.prepare_key(object())
@@ -47,34 +45,34 @@ class TestAlgorithms(unittest.TestCase):
self.assertEqual(str(exception), 'Expecting a string- or bytes-formatted key.')
def test_hmac_should_accept_unicode_key(self):
- algo = HMACAlgorithm(hashlib.sha256())
+ algo = HMACAlgorithm(HMACAlgorithm.SHA256)
algo.prepare_key(ensure_unicode('awesome'))
@unittest.skipIf(not has_crypto, 'Not supported without cryptography library')
def test_rsa_should_parse_pem_public_key(self):
- algo = RSAAlgorithm(hashes.SHA256())
+ algo = RSAAlgorithm(RSAAlgorithm.SHA256)
- with open('tests/keys/testkey2_rsa.pub.pem', 'r') as pem_key:
+ with open(key_path('testkey2_rsa.pub.pem'), 'r') as pem_key:
algo.prepare_key(pem_key.read())
@unittest.skipIf(not has_crypto, 'Not supported without cryptography library')
def test_rsa_should_accept_unicode_key(self):
- algo = RSAAlgorithm(hashes.SHA256())
+ algo = RSAAlgorithm(RSAAlgorithm.SHA256)
- with open('tests/keys/testkey_rsa', 'r') as rsa_key:
+ with open(key_path('testkey_rsa'), 'r') as rsa_key:
algo.prepare_key(ensure_unicode(rsa_key.read()))
@unittest.skipIf(not has_crypto, 'Not supported without cryptography library')
def test_rsa_should_reject_non_string_key(self):
- algo = RSAAlgorithm(hashes.SHA256())
+ algo = RSAAlgorithm(RSAAlgorithm.SHA256)
with self.assertRaises(TypeError):
algo.prepare_key(None)
@unittest.skipIf(not has_crypto, 'Not supported without cryptography library')
def test_rsa_verify_should_return_false_if_signature_invalid(self):
- algo = RSAAlgorithm(hashes.SHA256())
+ algo = RSAAlgorithm(RSAAlgorithm.SHA256)
jwt_message = ensure_bytes('Hello World!')
@@ -86,9 +84,9 @@ class TestAlgorithms(unittest.TestCase):
'fHJnNUzAEUOXS0WahHVb57D30pcgIji9z923q90p5c7E2cU8V+E1qe8NdCA'
'APCDzZZ9zQ/dgcMVaBrGrgimrcLbPjueOKFgSO+SSjIElKA=='))
- jwt_sig = jwt_sig + ensure_bytes('123') # Signature is now invalid
+ jwt_sig += ensure_bytes('123') # Signature is now invalid
- with open('tests/keys/testkey_rsa.pub', 'r') as keyfile:
+ with open(key_path('testkey_rsa.pub'), 'r') as keyfile:
jwt_pub_key = algo.prepare_key(keyfile.read())
result = algo.verify(jwt_message, jwt_pub_key, jwt_sig)
@@ -96,7 +94,7 @@ class TestAlgorithms(unittest.TestCase):
@unittest.skipIf(not has_crypto, 'Not supported without cryptography library')
def test_rsa_verify_should_return_true_if_signature_valid(self):
- algo = RSAAlgorithm(hashes.SHA256())
+ algo = RSAAlgorithm(RSAAlgorithm.SHA256)
jwt_message = ensure_bytes('Hello World!')
@@ -108,7 +106,7 @@ class TestAlgorithms(unittest.TestCase):
'fHJnNUzAEUOXS0WahHVb57D30pcgIji9z923q90p5c7E2cU8V+E1qe8NdCA'
'APCDzZZ9zQ/dgcMVaBrGrgimrcLbPjueOKFgSO+SSjIElKA=='))
- with open('tests/keys/testkey_rsa.pub', 'r') as keyfile:
+ with open(key_path('testkey_rsa.pub'), 'r') as keyfile:
jwt_pub_key = algo.prepare_key(keyfile.read())
result = algo.verify(jwt_message, jwt_pub_key, jwt_sig)
@@ -116,21 +114,21 @@ class TestAlgorithms(unittest.TestCase):
@unittest.skipIf(not has_crypto, 'Not supported without cryptography library')
def test_ec_should_reject_non_string_key(self):
- algo = ECAlgorithm(hashes.SHA256())
+ algo = ECAlgorithm(ECAlgorithm.SHA256)
with self.assertRaises(TypeError):
algo.prepare_key(None)
@unittest.skipIf(not has_crypto, 'Not supported without cryptography library')
def test_ec_should_accept_unicode_key(self):
- algo = ECAlgorithm(hashes.SHA256())
+ algo = ECAlgorithm(ECAlgorithm.SHA256)
- with open('tests/keys/testkey_ec', 'r') as ec_key:
+ with open(key_path('testkey_ec'), 'r') as ec_key:
algo.prepare_key(ensure_unicode(ec_key.read()))
@unittest.skipIf(not has_crypto, 'Not supported without cryptography library')
def test_ec_verify_should_return_false_if_signature_invalid(self):
- algo = ECAlgorithm(hashes.SHA256())
+ algo = ECAlgorithm(ECAlgorithm.SHA256)
jwt_message = ensure_bytes('Hello World!')
@@ -140,9 +138,9 @@ class TestAlgorithms(unittest.TestCase):
'6vdsVwm6Lrjs0Ag6ZqCf+olN11hVt1qKBC4lXppqB1gNWEmNQaiz1z2QRyc'
'zJ8hSJmbw=='))
- jwt_sig = ensure_bytes('123') # Signature is now invalid
+ jwt_sig += ensure_bytes('123') # Signature is now invalid
- with open('tests/keys/testkey_ec.pub', 'r') as keyfile:
+ with open(key_path('testkey_ec.pub'), 'r') as keyfile:
jwt_pub_key = algo.prepare_key(keyfile.read())
result = algo.verify(jwt_message, jwt_pub_key, jwt_sig)
@@ -150,7 +148,7 @@ class TestAlgorithms(unittest.TestCase):
@unittest.skipIf(not has_crypto, 'Not supported without cryptography library')
def test_ec_verify_should_return_true_if_signature_valid(self):
- algo = ECAlgorithm(hashes.SHA256())
+ algo = ECAlgorithm(ECAlgorithm.SHA256)
jwt_message = ensure_bytes('Hello World!')
@@ -160,7 +158,7 @@ class TestAlgorithms(unittest.TestCase):
'6vdsVwm6Lrjs0Ag6ZqCf+olN11hVt1qKBC4lXppqB1gNWEmNQaiz1z2QRyc'
'zJ8hSJmbw=='))
- with open('tests/keys/testkey_ec.pub', 'r') as keyfile:
+ with open(key_path('testkey_ec.pub'), 'r') as keyfile:
jwt_pub_key = algo.prepare_key(keyfile.read())
result = algo.verify(jwt_message, jwt_pub_key, jwt_sig)
diff --git a/tests/utils.py b/tests/utils.py
index 7b6d70e..4d455b5 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -1,3 +1,5 @@
+import os
+
from .compat import text_type
@@ -13,3 +15,8 @@ def ensure_unicode(key):
key = key.decode()
return key
+
+
+def key_path(key_name):
+ return os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ 'keys', key_name)
diff --git a/tox.ini b/tox.ini
index 5a46b7d..2c14a5a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = py26, py27, py32, py33, py34, py34-nocrypto, pep8
+envlist = py26, py27, py27-contrib-crypto, py27-nocrypto, py32, py33, py34, py34-contrib-crypto, py34-nocrypto, pep8
[testenv]
commands =
@@ -11,6 +11,28 @@ deps =
unittest2
coverage
+[testenv:py34-contrib-crypto]
+basepython = python3.4
+commands =
+ coverage erase
+ coverage run setup.py test
+ coverage report -m
+deps =
+ pycrypto
+ ecdsa
+ coverage
+
+[testenv:py27-contrib-crypto]
+basepython = python2.7
+commands =
+ coverage erase
+ coverage run setup.py test
+ coverage report -m
+deps =
+ pycrypto
+ ecdsa
+ coverage
+
[testenv:py34-nocrypto]
basepython = python3.4
commands =
@@ -35,6 +57,5 @@ deps =
flake8
flake8-import-order
pep8-naming
- unittest2
commands =
flake8