diff options
author | Mark Adams <mark@markadams.me> | 2016-11-30 19:46:48 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-30 19:46:48 -0600 |
commit | 7dd3d4a16ca270d6de8db077b7c61abc0f4d2f0d (patch) | |
tree | 9a363228874fbbf8faa4e72aece5c0bc8e277f7d | |
parent | 5caa1af9d57c3621596a12aeaa4693bda5f15596 (diff) | |
parent | 439f9a33389193ceacfe188127cae6f0b61d7f73 (diff) | |
download | pyjwt-7dd3d4a16ca270d6de8db077b7c61abc0f4d2f0d.tar.gz |
Merge pull request #231 from vimalloc/master
Better error messages when missing cryptography package
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | jwt/__main__.py | 1 | ||||
-rw-r--r-- | jwt/algorithms.py | 4 | ||||
-rw-r--r-- | jwt/api_jws.py | 13 | ||||
-rw-r--r-- | tests/keys/__init__.py | 1 | ||||
-rw-r--r-- | tests/test_api_jws.py | 6 | ||||
-rw-r--r-- | tests/utils.py | 1 |
7 files changed, 25 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index b5c398e..37b6ffd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ------------------------------------------------------------------------- ### Changed - Renamed commandline script `jwt` to `jwt-cli` to avoid issues with the script clobbering the `jwt` module in some circumstances. +- Better error messages when using an algorithm that requires the cryptography package, but it isn't available [#230][230] ### Fixed diff --git a/jwt/__main__.py b/jwt/__main__.py index 94abf2a..6a36953 100644 --- a/jwt/__main__.py +++ b/jwt/__main__.py @@ -131,5 +131,6 @@ The exp key is special and can take an offset to current Unix time.\ else:
p.print_help()
+
if __name__ == '__main__':
main()
diff --git a/jwt/algorithms.py b/jwt/algorithms.py index 893833b..2fe1883 100644 --- a/jwt/algorithms.py +++ b/jwt/algorithms.py @@ -31,6 +31,9 @@ try: except ImportError: has_crypto = False +requires_cryptography = set(['RS256', 'RS384', 'RS512', 'ES256', 'ES384', + 'ES521', 'ES512', 'PS256', 'PS384', 'PS512']) + def get_default_algorithms(): """ @@ -171,6 +174,7 @@ class HMACAlgorithm(Algorithm): def verify(self, msg, key, sig): return constant_time_compare(sig, self.sign(msg, key)) + if has_crypto: class RSAAlgorithm(Algorithm): diff --git a/jwt/api_jws.py b/jwt/api_jws.py index f4e58b7..66b6a67 100644 --- a/jwt/api_jws.py +++ b/jwt/api_jws.py @@ -4,7 +4,9 @@ import warnings from collections import Mapping -from .algorithms import Algorithm, get_default_algorithms # NOQA +from .algorithms import ( + Algorithm, get_default_algorithms, has_crypto, requires_cryptography # NOQA +) from .compat import binary_type, string_types, text_type from .exceptions import DecodeError, InvalidAlgorithmError, InvalidTokenError from .utils import base64url_decode, base64url_encode, force_bytes, merge_dict @@ -101,7 +103,13 @@ class PyJWS(object): signature = alg_obj.sign(signing_input, key) except KeyError: - raise NotImplementedError('Algorithm not supported') + if not has_crypto and algorithm in requires_cryptography: + raise NotImplementedError( + "Algorithm '%s' could not be found. Do you have cryptography " + "installed?" % algorithm + ) + else: + raise NotImplementedError('Algorithm not supported') segments.append(base64url_encode(signature)) @@ -198,6 +206,7 @@ class PyJWS(object): if not isinstance(kid, string_types): raise InvalidTokenError('Key ID header parameter must be a string') + _jws_global_obj = PyJWS() encode = _jws_global_obj.encode decode = _jws_global_obj.decode diff --git a/tests/keys/__init__.py b/tests/keys/__init__.py index 4fae687..3727378 100644 --- a/tests/keys/__init__.py +++ b/tests/keys/__init__.py @@ -19,6 +19,7 @@ def load_hmac_key(): return base64url_decode(force_bytes(keyobj['k'])) + try: from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.backends import default_backend diff --git a/tests/test_api_jws.py b/tests/test_api_jws.py index 403735d..053dd11 100644 --- a/tests/test_api_jws.py +++ b/tests/test_api_jws.py @@ -303,6 +303,12 @@ class TestJWS: with pytest.raises(NotImplementedError): jws.encode(payload, 'secret', algorithm='HS1024') + @pytest.mark.skipif(has_crypto, reason='Scenario requires cryptography to not be installed') + def test_missing_crypto_library_better_error_messages(self, jws, payload): + with pytest.raises(NotImplementedError) as excinfo: + jws.encode(payload, 'secret', algorithm='RS256') + assert 'cryptography' in str(excinfo.value) + def test_unicode_secret(self, jws, payload): secret = '\xc2' jws_message = jws.encode(payload, secret) diff --git a/tests/utils.py b/tests/utils.py index 2e3f043..79c77b0 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -13,6 +13,7 @@ def key_path(key_name): return os.path.join(os.path.dirname(os.path.realpath(__file__)), 'keys', key_name) + # Borrowed from `cryptography` if hasattr(int, "from_bytes"): int_from_bytes = int.from_bytes |