From 1922f0972b065077404c0dafa0946f2132400a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Padilla?= Date: Wed, 21 Jun 2017 15:49:41 -0400 Subject: [PATCH 1/3] Throw if key is an PKCS1 PEM-encoded public key --- jwt/algorithms.py | 1 + tests/keys/testkey_pkcs1.pub.pem | 5 +++++ tests/test_algorithms.py | 7 +++++++ 3 files changed, 13 insertions(+) create mode 100644 tests/keys/testkey_pkcs1.pub.pem diff --git a/jwt/algorithms.py b/jwt/algorithms.py index f6d990ad..47043c34 100644 --- a/jwt/algorithms.py +++ b/jwt/algorithms.py @@ -142,6 +142,7 @@ def prepare_key(self, key): invalid_strings = [ b'-----BEGIN PUBLIC KEY-----', b'-----BEGIN CERTIFICATE-----', + b'-----BEGIN RSA PUBLIC KEY-----', b'ssh-rsa' ] diff --git a/tests/keys/testkey_pkcs1.pub.pem b/tests/keys/testkey_pkcs1.pub.pem new file mode 100644 index 00000000..f690179c --- /dev/null +++ b/tests/keys/testkey_pkcs1.pub.pem @@ -0,0 +1,5 @@ +-----BEGIN RSA PUBLIC KEY----- +MIGHAoGBAOV/0Vl/5VdHcYpnILYzBGWo5JQVzo9wBkbxzjAStcAnTwvv1ZJTMXs6 +fjz91f9hiMM4Z/5qNTE/EHlDWxVdj1pyRaQulZPUs0r9qJ02ogRRGLG3jjrzzbzF +yj/pdNBwym0UJYC/Jmn/kMLwGiWI2nfa9vM5SovqZiAy2FD7eOtVAgED +-----END RSA PUBLIC KEY----- diff --git a/tests/test_algorithms.py b/tests/test_algorithms.py index 11d8cd08..317bf3a9 100644 --- a/tests/test_algorithms.py +++ b/tests/test_algorithms.py @@ -97,6 +97,13 @@ def test_hmac_should_throw_exception_if_key_is_x509_cert(self): with open(key_path('testkey2_rsa.pub.pem'), 'r') as keyfile: algo.prepare_key(keyfile.read()) + def test_hmac_should_throw_exception_if_key_is_pkcs1_pem_public(self): + algo = HMACAlgorithm(HMACAlgorithm.SHA256) + + with pytest.raises(InvalidKeyError): + with open(key_path('testkey_pkcs1.pub.pem'), 'r') as keyfile: + algo.prepare_key(keyfile.read()) + def test_hmac_jwk_should_parse_and_verify(self): algo = HMACAlgorithm(HMACAlgorithm.SHA256) From 7628c6ffef4f1e211cfa82c239db57b0e7d487cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Padilla?= Date: Wed, 21 Jun 2017 16:04:35 -0400 Subject: [PATCH 2/3] Add warning when decoding with no algorithms specified --- jwt/api_jws.py | 9 +++++++++ jwt/api_jwt.py | 9 +++++++++ tests/test_api_jws.py | 10 ++++++++++ tests/test_api_jwt.py | 10 ++++++++++ 4 files changed, 38 insertions(+) diff --git a/jwt/api_jws.py b/jwt/api_jws.py index 8910751d..04f3745d 100644 --- a/jwt/api_jws.py +++ b/jwt/api_jws.py @@ -117,6 +117,15 @@ def encode(self, payload, key, algorithm='HS256', headers=None, def decode(self, jws, key='', verify=True, algorithms=None, options=None, **kwargs): + + if not algorithms: + warnings.warn( + 'It is strongly recommended that you pass in a ' + + 'value for the "algorithms" argument when calling decode(). ' + + 'This argument will be mandatory in a future version.', + DeprecationWarning + ) + payload, signing_input, header, signature = self._load(jws) if verify: diff --git a/jwt/api_jwt.py b/jwt/api_jwt.py index eef2b0fb..9da5cf5e 100644 --- a/jwt/api_jwt.py +++ b/jwt/api_jwt.py @@ -58,6 +58,15 @@ def encode(self, payload, key, algorithm='HS256', headers=None, def decode(self, jwt, key='', verify=True, algorithms=None, options=None, **kwargs): + + if not algorithms: + warnings.warn( + 'It is strongly recommended that you pass in a ' + + 'value for the "algorithms" argument when calling decode(). ' + + 'This argument will be mandatory in a future version.', + DeprecationWarning + ) + payload, signing_input, header, signature = self._load(jwt) decoded = super(PyJWT, self).decode(jwt, key, verify, algorithms, diff --git a/tests/test_api_jws.py b/tests/test_api_jws.py index 053dd117..c90fda22 100644 --- a/tests/test_api_jws.py +++ b/tests/test_api_jws.py @@ -265,6 +265,16 @@ def test_verify_false_deprecated(self, jws, recwarn): pytest.deprecated_call(jws.decode, example_jws, verify=False) + def test_decode_with_optional_algorithms(self, jws): + example_secret = 'secret' + example_jws = ( + b'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.' + b'aGVsbG8gd29ybGQ.' + b'SIr03zM64awWRdPrAM_61QWsZchAtgDV3pphfHPPWkI' + ) + + pytest.deprecated_call(jws.decode, example_jws, key=example_secret) + def test_load_no_verification(self, jws, payload): right_secret = 'foo' jws_message = jws.encode(payload, right_secret) diff --git a/tests/test_api_jwt.py b/tests/test_api_jwt.py index 61de6e05..798e4b7a 100644 --- a/tests/test_api_jwt.py +++ b/tests/test_api_jwt.py @@ -472,3 +472,13 @@ def test_decode_with_verify_expiration_kwarg(self, jwt, payload): secret, verify_expiration=True ) + + def test_decode_with_optional_algorithms(self, jwt, payload): + secret = 'secret' + jwt_message = jwt.encode(payload, secret) + + pytest.deprecated_call( + jwt.decode, + jwt_message, + secret + ) From f812f699be24fa515e5244b9a5e0ccb9cd6fed47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Padilla?= Date: Thu, 22 Jun 2017 09:26:52 -0400 Subject: [PATCH 3/3] Update CHANGELOG.md --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 794fe43d..654fa370 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,20 @@ This project adheres to [Semantic Versioning](http://semver.org/). [Unreleased][unreleased] ------------------------------------------------------------------------- ### Changed +### Fixed +### Added + +[v1.5.1][1.5.1] +------------------------------------------------------------------------- +### Changed - Change optparse for argparse. [#238][238] ### Fixed +- Guard against PKCS1 PEM encododed public keys +- Add deprecation warning when decoding without specifying `algorithms` + ### Added - Support for Python 3.6 [#262][262] @@ -132,6 +141,7 @@ rarely used. Users affected by this should upgrade to 3.3+. [1.4.1]: https://github.com/jpadilla/pyjwt/compare/1.4.0...1.4.1 [1.4.2]: https://github.com/jpadilla/pyjwt/compare/1.4.1...1.4.2 [1.5.0]: https://github.com/jpadilla/pyjwt/compare/1.4.2...1.5.0 +[1.5.1]: https://github.com/jpadilla/pyjwt/compare/1.5.0...1.5.1 [109]: https://github.com/jpadilla/pyjwt/pull/109 [110]: https://github.com/jpadilla/pyjwt/pull/110