From 75257daa6d21a1e79565176f7ee90c3ebb4a4680 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 16 Dec 2014 22:08:09 -0600 Subject: add OpenSSH DSS public key loading fixes #1531 --- .../hazmat/primitives/serialization.py | 40 ++++++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/cryptography/hazmat/primitives/serialization.py b/src/cryptography/hazmat/primitives/serialization.py index 0dbbc85c..1949b111 100644 --- a/src/cryptography/hazmat/primitives/serialization.py +++ b/src/cryptography/hazmat/primitives/serialization.py @@ -10,6 +10,9 @@ import warnings from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.hazmat.primitives.asymmetric.dsa import ( + DSAParameterNumbers, DSAPublicNumbers +) from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers @@ -55,13 +58,14 @@ def load_ssh_public_key(data, backend): key_type = key_parts[0] key_body = key_parts[1] - if not key_type.startswith(b'ssh-'): - raise ValueError('SSH-formatted keys must begin with \'ssh-\'.') - - if not key_type.startswith(b'ssh-rsa'): - raise UnsupportedAlgorithm('Only RSA keys are currently supported.') - - return _load_ssh_rsa_public_key(key_body, backend) + if key_type.startswith(b'ssh-rsa'): + return _load_ssh_rsa_public_key(key_body, backend) + elif key_type.startswith(b'ssh-dss'): + return _load_ssh_dss_public_key(key_body, backend) + else: + raise UnsupportedAlgorithm( + 'Only RSA and DSA keys are currently supported.' + ) def _load_ssh_rsa_public_key(key_body, backend): @@ -81,6 +85,28 @@ 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) + p, rest = _read_next_mpint(rest) + q, rest = _read_next_mpint(rest) + g, rest = _read_next_mpint(rest) + y, rest = _read_next_mpint(rest) + + if key_type != b'ssh-dss': + raise ValueError( + 'Key header and key body contain different key type values.') + + if rest: + raise ValueError('Key body contains extra bytes.') + + parameter_numbers = DSAParameterNumbers(p, q, g) + public_numbers = DSAPublicNumbers(y, parameter_numbers) + + return backend.load_dsa_public_numbers(public_numbers) + + def _read_next_string(data): """Retrieves the next RFC 4251 string value from the data.""" str_len, = struct.unpack('>I', data[:4]) -- cgit v1.2.3 From 2cfa45fd168273eaf3b616730255fc063faf5257 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 17 Dec 2014 08:42:42 -0600 Subject: update docs, hoist b64decode up and re-add test for it --- src/cryptography/hazmat/primitives/serialization.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'src') 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) -- cgit v1.2.3 From 646c2a6630ee694c86a489426386de9c0c53269b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 17 Dec 2014 13:25:45 -0600 Subject: use the right comparison --- src/cryptography/hazmat/primitives/serialization.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cryptography/hazmat/primitives/serialization.py b/src/cryptography/hazmat/primitives/serialization.py index 61a69a5d..9d384fc7 100644 --- a/src/cryptography/hazmat/primitives/serialization.py +++ b/src/cryptography/hazmat/primitives/serialization.py @@ -63,9 +63,9 @@ def load_ssh_public_key(data, backend): except TypeError: raise ValueError('Key is not in the proper format.') - if key_type.startswith(b'ssh-rsa'): + if key_type == b'ssh-rsa': return _load_ssh_rsa_public_key(decoded_data, backend) - elif key_type.startswith(b'ssh-dss'): + elif key_type == b'ssh-dss': return _load_ssh_dss_public_key(decoded_data, backend) else: raise UnsupportedAlgorithm( -- cgit v1.2.3