diff options
-rw-r--r-- | docs/hazmat/primitives/asymmetric/serialization.rst | 13 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/serialization.py | 21 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_serialization.py | 8 |
3 files changed, 27 insertions, 15 deletions
diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst index a9392c7b..b523c342 100644 --- a/docs/hazmat/primitives/asymmetric/serialization.rst +++ b/docs/hazmat/primitives/asymmetric/serialization.rst @@ -201,8 +201,8 @@ OpenSSH Public Key The format used by OpenSSH to store public keys, as specified in :rfc:`4253`. -Currently, only RSA public keys are supported. Any other type of key will -result in an exception being thrown. +Currently, only RSA and DSA public keys are supported. Any other type of key +will result in an exception being thrown. An example RSA key in OpenSSH format (line breaks added for formatting purposes):: @@ -215,6 +215,9 @@ purposes):: ///ImSCGHQRvhwariN2tvZ6CBNSLh3iQgeB0AkyJlng7MXB2qYq/Ci2FUOryCX 2MzHvnbv testkey@localhost +DSA keys look almost identical but begin with ``ssh-dss`` rather than +``ssh-rsa``. + .. function:: load_ssh_public_key(data, backend) .. versionadded:: 0.7 @@ -224,8 +227,10 @@ purposes):: :param bytes data: The OpenSSH encoded key data. - :param backend: An - :class:`~cryptography.hazmat.backends.interfaces.RSABackend` provider. + :param backend: A backend providing + :class:`~cryptography.hazmat.backends.interfaces.RSABackend` or + :class:`~cryptography.hazmat.backends.interfaces.DSABackend` depending + on key type. :returns: A new instance of a public key type. diff --git a/src/cryptography/hazmat/primitives/serialization.py b/src/cryptography/hazmat/primitives/serialization.py index 1949b111..61a69a5d 100644 --- a/src/cryptography/hazmat/primitives/serialization.py +++ b/src/cryptography/hazmat/primitives/serialization.py @@ -58,20 +58,23 @@ def load_ssh_public_key(data, backend): key_type = key_parts[0] key_body = key_parts[1] + try: + decoded_data = base64.b64decode(key_body) + except TypeError: + raise ValueError('Key is not in the proper format.') + if key_type.startswith(b'ssh-rsa'): - return _load_ssh_rsa_public_key(key_body, backend) + return _load_ssh_rsa_public_key(decoded_data, backend) elif key_type.startswith(b'ssh-dss'): - return _load_ssh_dss_public_key(key_body, backend) + return _load_ssh_dss_public_key(decoded_data, backend) else: raise UnsupportedAlgorithm( 'Only RSA and DSA keys are currently supported.' ) -def _load_ssh_rsa_public_key(key_body, backend): - data = base64.b64decode(key_body) - - key_type, rest = _read_next_string(data) +def _load_ssh_rsa_public_key(decoded_data, backend): + key_type, rest = _read_next_string(decoded_data) e, rest = _read_next_mpint(rest) n, rest = _read_next_mpint(rest) @@ -85,10 +88,8 @@ def _load_ssh_rsa_public_key(key_body, backend): return backend.load_rsa_public_numbers(RSAPublicNumbers(e, n)) -def _load_ssh_dss_public_key(key_body, backend): - data = base64.b64decode(key_body) - - key_type, rest = _read_next_string(data) +def _load_ssh_dss_public_key(decoded_data, backend): + key_type, rest = _read_next_string(decoded_data) p, rest = _read_next_mpint(rest) q, rest = _read_next_mpint(rest) g, rest = _read_next_mpint(rest) diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index de0ca702..91db318c 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -690,11 +690,17 @@ class TestPKCS8Serialization(object): @pytest.mark.requires_backend_interface(interface=RSABackend) class TestRSASSHSerialization(object): def test_load_ssh_public_key_unsupported(self, backend): - ssh_key = b'ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTY...' + ssh_key = b'ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTY=' with pytest.raises(UnsupportedAlgorithm): load_ssh_public_key(ssh_key, backend) + def test_load_ssh_public_key_bad_format(self, backend): + ssh_key = b'ssh-rsa not-a-real-key' + + with pytest.raises(ValueError): + load_ssh_public_key(ssh_key, backend) + def test_load_ssh_public_key_rsa_too_short(self, backend): ssh_key = b'ssh-rsa' |