From 299d196383836e1f804ef4441365a94862e08abe Mon Sep 17 00:00:00 2001 From: Mark Adams Date: Tue, 14 Mar 2017 07:21:12 -0500 Subject: [PATCH 1/2] Add a failing test for OpenSSH-formatted ECDSA public keys --- tests/keys/testkey_ec_ssh.pub | 1 + tests/test_algorithms.py | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 tests/keys/testkey_ec_ssh.pub diff --git a/tests/keys/testkey_ec_ssh.pub b/tests/keys/testkey_ec_ssh.pub new file mode 100644 index 00000000..4fa3a6bb --- /dev/null +++ b/tests/keys/testkey_ec_ssh.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAFZwnA8QCdL+TiQWBSHE0XsnRJBCFkb6c2DL7+ZfCFDk9khSYh3VrVOOQ1eIrO/oOm20Gp24dvP9XQS0f5B9bLQHgGFnkydPIMaNzPUNCop17F5uHOhtuFIhmOlh3lpTjyj2ten86cCetqN12kawnRs1/iu0wsGoVgk3os6yUAHvFMFGA== diff --git a/tests/test_algorithms.py b/tests/test_algorithms.py index 97fdc225..11d8cd08 100644 --- a/tests/test_algorithms.py +++ b/tests/test_algorithms.py @@ -375,6 +375,13 @@ def test_ec_should_accept_pem_private_key_bytes(self): with open(key_path('testkey_ec'), 'rb') as ec_key: algo.prepare_key(ec_key.read()) + @pytest.mark.skipif(not has_crypto, reason='Not supported without cryptography library') + def test_ec_should_accept_ssh_public_key_bytes(self): + algo = ECAlgorithm(ECAlgorithm.SHA256) + + with open(key_path('testkey_ec_ssh.pub'), 'r') as ec_key: + algo.prepare_key(ec_key.read()) + @pytest.mark.skipif(not has_crypto, reason='Not supported without cryptography library') def test_ec_verify_should_return_false_if_signature_invalid(self): algo = ECAlgorithm(ECAlgorithm.SHA256) From 1710c1524c69c39dfece7a24b87179be5eeff217 Mon Sep 17 00:00:00 2001 From: Mark Adams Date: Tue, 14 Mar 2017 07:33:57 -0500 Subject: [PATCH 2/2] Add support for public keys in OpenSSH (RFC 4253) format. Cryptography previously lacked support for ECDSA keys in RFC 4253 format. Now that they have support for those keys, we should take advantage of it and support them in PyJWT. Implements #243. --- CHANGELOG.md | 2 ++ jwt/algorithms.py | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37b6ffda..060876c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). [Unreleased][unreleased] ------------------------------------------------------------------------- ### Changed +- Add support for ECDSA public keys in RFC 4253 (OpenSSH) format [#244][244] - 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] @@ -129,3 +130,4 @@ rarely used. Users affected by this should upgrade to 3.3+. [182]: https://github.com/jpadilla/pyjwt/pull/182 [183]: https://github.com/jpadilla/pyjwt/pull/183 [213]: https://github.com/jpadilla/pyjwt/pull/214 +[244]: https://github.com/jpadilla/pyjwt/pull/244 diff --git a/jwt/algorithms.py b/jwt/algorithms.py index 2fe1883b..f6d990ad 100644 --- a/jwt/algorithms.py +++ b/jwt/algorithms.py @@ -356,7 +356,10 @@ def prepare_key(self, key): # a Signing Key or a Verifying Key, so we try # the Verifying Key first. try: - key = load_pem_public_key(key, backend=default_backend()) + if key.startswith(b'ecdsa-sha2-'): + key = load_ssh_public_key(key, backend=default_backend()) + else: + key = load_pem_public_key(key, backend=default_backend()) except ValueError: key = load_pem_private_key(key, password=None, backend=default_backend())