We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add support for loading DSA OpenSSH public keys
Should be straightforward to add support to the existing code.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/cryptography/hazmat/primitives/serialization.py`
Content:
```
1 # This file is dual licensed under the terms of the Apache License, Version
2 # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3 # for complete details.
4 
5 from __future__ import absolute_import, division, print_function
6 
7 import base64
8 import struct
9 import warnings
10 
11 from cryptography import utils
12 from cryptography.exceptions import UnsupportedAlgorithm
13 from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers
14 
15 
16 def load_pem_traditional_openssl_private_key(data, password, backend):
17     warnings.warn(
18         "load_pem_traditional_openssl_private_key is deprecated and will be "
19         "removed in a future version, use load_pem_private_key instead.",
20         utils.DeprecatedIn06,
21         stacklevel=2
22     )
23 
24     return backend.load_traditional_openssl_pem_private_key(
25         data, password
26     )
27 
28 
29 def load_pem_pkcs8_private_key(data, password, backend):
30     warnings.warn(
31         "load_pem_pkcs8_private_key is deprecated and will be removed in a "
32         "future version, use load_pem_private_key instead.",
33         utils.DeprecatedIn06,
34         stacklevel=2
35     )
36 
37     return backend.load_pkcs8_pem_private_key(data, password)
38 
39 
40 def load_pem_private_key(data, password, backend):
41     return backend.load_pem_private_key(data, password)
42 
43 
44 def load_pem_public_key(data, backend):
45     return backend.load_pem_public_key(data)
46 
47 
48 def load_ssh_public_key(data, backend):
49     key_parts = data.split(b' ')
50 
51     if len(key_parts) != 2 and len(key_parts) != 3:
52         raise ValueError(
53             'Key is not in the proper format or contains extra data.')
54 
55     key_type = key_parts[0]
56     key_body = key_parts[1]
57 
58     if not key_type.startswith(b'ssh-'):
59         raise ValueError('SSH-formatted keys must begin with \'ssh-\'.')
60 
61     if not key_type.startswith(b'ssh-rsa'):
62         raise UnsupportedAlgorithm('Only RSA keys are currently supported.')
63 
64     return _load_ssh_rsa_public_key(key_body, backend)
65 
66 
67 def _load_ssh_rsa_public_key(key_body, backend):
68     data = base64.b64decode(key_body)
69 
70     key_type, rest = _read_next_string(data)
71     e, rest = _read_next_mpint(rest)
72     n, rest = _read_next_mpint(rest)
73 
74     if key_type != b'ssh-rsa':
75         raise ValueError(
76             'Key header and key body contain different key type values.')
77 
78     if rest:
79         raise ValueError('Key body contains extra bytes.')
80 
81     return backend.load_rsa_public_numbers(RSAPublicNumbers(e, n))
82 
83 
84 def _read_next_string(data):
85     """Retrieves the next RFC 4251 string value from the data."""
86     str_len, = struct.unpack('>I', data[:4])
87     return data[4:4 + str_len], data[4 + str_len:]
88 
89 
90 def _read_next_mpint(data):
91     """
92     Reads the next mpint from the data.
93 
94     Currently, all mpints are interpreted as unsigned.
95     """
96     mpint_data, rest = _read_next_string(data)
97 
98     return _int_from_bytes(mpint_data, byteorder='big', signed=False), rest
99 
100 
101 if hasattr(int, "from_bytes"):
102     _int_from_bytes = int.from_bytes
103 else:
104     def _int_from_bytes(data, byteorder, signed=False):
105         assert byteorder == 'big'
106         assert not signed
107 
108         if len(data) % 4 != 0:
109             data = (b'\x00' * (4 - (len(data) % 4))) + data
110 
111         result = 0
112 
113         while len(data) > 0:
114             digit, = struct.unpack('>I', data[:4])
115             result = (result << 32) + digit
116             data = data[4:]
117 
118         return result
119
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/cryptography/hazmat/primitives/serialization.py b/src/cryptography/hazmat/primitives/serialization.py
--- a/src/cryptography/hazmat/primitives/serialization.py
+++ b/src/cryptography/hazmat/primitives/serialization.py
@@ -10,6 +10,9 @@
 
 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,19 +58,23 @@
     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-\'.')
+    try:
+        decoded_data = base64.b64decode(key_body)
+    except TypeError:
+        raise ValueError('Key is not in the proper format.')
 
-    if not key_type.startswith(b'ssh-rsa'):
-        raise UnsupportedAlgorithm('Only RSA keys are currently supported.')
+    if key_type == b'ssh-rsa':
+        return _load_ssh_rsa_public_key(decoded_data, backend)
+    elif key_type == b'ssh-dss':
+        return _load_ssh_dss_public_key(decoded_data, backend)
+    else:
+        raise UnsupportedAlgorithm(
+            'Only RSA and DSA keys are currently supported.'
+        )
 
-    return _load_ssh_rsa_public_key(key_body, backend)
 
-
-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)
 
@@ -81,6 +88,26 @@
     return backend.load_rsa_public_numbers(RSAPublicNumbers(e, n))
 
 
+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)
+    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])

{"golden_diff": "diff --git a/src/cryptography/hazmat/primitives/serialization.py b/src/cryptography/hazmat/primitives/serialization.py\n--- a/src/cryptography/hazmat/primitives/serialization.py\n+++ b/src/cryptography/hazmat/primitives/serialization.py\n@@ -10,6 +10,9 @@\n \n from cryptography import utils\n from cryptography.exceptions import UnsupportedAlgorithm\n+from cryptography.hazmat.primitives.asymmetric.dsa import (\n+    DSAParameterNumbers, DSAPublicNumbers\n+)\n from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers\n \n \n@@ -55,19 +58,23 @@\n     key_type = key_parts[0]\n     key_body = key_parts[1]\n \n-    if not key_type.startswith(b'ssh-'):\n-        raise ValueError('SSH-formatted keys must begin with \\'ssh-\\'.')\n+    try:\n+        decoded_data = base64.b64decode(key_body)\n+    except TypeError:\n+        raise ValueError('Key is not in the proper format.')\n \n-    if not key_type.startswith(b'ssh-rsa'):\n-        raise UnsupportedAlgorithm('Only RSA keys are currently supported.')\n+    if key_type == b'ssh-rsa':\n+        return _load_ssh_rsa_public_key(decoded_data, backend)\n+    elif key_type == b'ssh-dss':\n+        return _load_ssh_dss_public_key(decoded_data, backend)\n+    else:\n+        raise UnsupportedAlgorithm(\n+            'Only RSA and DSA keys are currently supported.'\n+        )\n \n-    return _load_ssh_rsa_public_key(key_body, backend)\n \n-\n-def _load_ssh_rsa_public_key(key_body, backend):\n-    data = base64.b64decode(key_body)\n-\n-    key_type, rest = _read_next_string(data)\n+def _load_ssh_rsa_public_key(decoded_data, backend):\n+    key_type, rest = _read_next_string(decoded_data)\n     e, rest = _read_next_mpint(rest)\n     n, rest = _read_next_mpint(rest)\n \n@@ -81,6 +88,26 @@\n     return backend.load_rsa_public_numbers(RSAPublicNumbers(e, n))\n \n \n+def _load_ssh_dss_public_key(decoded_data, backend):\n+    key_type, rest = _read_next_string(decoded_data)\n+    p, rest = _read_next_mpint(rest)\n+    q, rest = _read_next_mpint(rest)\n+    g, rest = _read_next_mpint(rest)\n+    y, rest = _read_next_mpint(rest)\n+\n+    if key_type != b'ssh-dss':\n+        raise ValueError(\n+            'Key header and key body contain different key type values.')\n+\n+    if rest:\n+        raise ValueError('Key body contains extra bytes.')\n+\n+    parameter_numbers = DSAParameterNumbers(p, q, g)\n+    public_numbers = DSAPublicNumbers(y, parameter_numbers)\n+\n+    return backend.load_dsa_public_numbers(public_numbers)\n+\n+\n def _read_next_string(data):\n     \"\"\"Retrieves the next RFC 4251 string value from the data.\"\"\"\n     str_len, = struct.unpack('>I', data[:4])\n", "issue": "Add support for loading DSA OpenSSH public keys\nShould be straightforward to add support to the existing code.\n\n", "before_files": [{"content": "# This file is dual licensed under the terms of the Apache License, Version\n# 2.0, and the BSD License. See the LICENSE file in the root of this repository\n# for complete details.\n\nfrom __future__ import absolute_import, division, print_function\n\nimport base64\nimport struct\nimport warnings\n\nfrom cryptography import utils\nfrom cryptography.exceptions import UnsupportedAlgorithm\nfrom cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers\n\n\ndef load_pem_traditional_openssl_private_key(data, password, backend):\n    warnings.warn(\n        \"load_pem_traditional_openssl_private_key is deprecated and will be \"\n        \"removed in a future version, use load_pem_private_key instead.\",\n        utils.DeprecatedIn06,\n        stacklevel=2\n    )\n\n    return backend.load_traditional_openssl_pem_private_key(\n        data, password\n    )\n\n\ndef load_pem_pkcs8_private_key(data, password, backend):\n    warnings.warn(\n        \"load_pem_pkcs8_private_key is deprecated and will be removed in a \"\n        \"future version, use load_pem_private_key instead.\",\n        utils.DeprecatedIn06,\n        stacklevel=2\n    )\n\n    return backend.load_pkcs8_pem_private_key(data, password)\n\n\ndef load_pem_private_key(data, password, backend):\n    return backend.load_pem_private_key(data, password)\n\n\ndef load_pem_public_key(data, backend):\n    return backend.load_pem_public_key(data)\n\n\ndef load_ssh_public_key(data, backend):\n    key_parts = data.split(b' ')\n\n    if len(key_parts) != 2 and len(key_parts) != 3:\n        raise ValueError(\n            'Key is not in the proper format or contains extra data.')\n\n    key_type = key_parts[0]\n    key_body = key_parts[1]\n\n    if not key_type.startswith(b'ssh-'):\n        raise ValueError('SSH-formatted keys must begin with \\'ssh-\\'.')\n\n    if not key_type.startswith(b'ssh-rsa'):\n        raise UnsupportedAlgorithm('Only RSA keys are currently supported.')\n\n    return _load_ssh_rsa_public_key(key_body, backend)\n\n\ndef _load_ssh_rsa_public_key(key_body, backend):\n    data = base64.b64decode(key_body)\n\n    key_type, rest = _read_next_string(data)\n    e, rest = _read_next_mpint(rest)\n    n, rest = _read_next_mpint(rest)\n\n    if key_type != b'ssh-rsa':\n        raise ValueError(\n            'Key header and key body contain different key type values.')\n\n    if rest:\n        raise ValueError('Key body contains extra bytes.')\n\n    return backend.load_rsa_public_numbers(RSAPublicNumbers(e, n))\n\n\ndef _read_next_string(data):\n    \"\"\"Retrieves the next RFC 4251 string value from the data.\"\"\"\n    str_len, = struct.unpack('>I', data[:4])\n    return data[4:4 + str_len], data[4 + str_len:]\n\n\ndef _read_next_mpint(data):\n    \"\"\"\n    Reads the next mpint from the data.\n\n    Currently, all mpints are interpreted as unsigned.\n    \"\"\"\n    mpint_data, rest = _read_next_string(data)\n\n    return _int_from_bytes(mpint_data, byteorder='big', signed=False), rest\n\n\nif hasattr(int, \"from_bytes\"):\n    _int_from_bytes = int.from_bytes\nelse:\n    def _int_from_bytes(data, byteorder, signed=False):\n        assert byteorder == 'big'\n        assert not signed\n\n        if len(data) % 4 != 0:\n            data = (b'\\x00' * (4 - (len(data) % 4))) + data\n\n        result = 0\n\n        while len(data) > 0:\n            digit, = struct.unpack('>I', data[:4])\n            result = (result << 32) + digit\n            data = data[4:]\n\n        return result\n", "path": "src/cryptography/hazmat/primitives/serialization.py"}], "after_files": [{"content": "# This file is dual licensed under the terms of the Apache License, Version\n# 2.0, and the BSD License. See the LICENSE file in the root of this repository\n# for complete details.\n\nfrom __future__ import absolute_import, division, print_function\n\nimport base64\nimport struct\nimport warnings\n\nfrom cryptography import utils\nfrom cryptography.exceptions import UnsupportedAlgorithm\nfrom cryptography.hazmat.primitives.asymmetric.dsa import (\n    DSAParameterNumbers, DSAPublicNumbers\n)\nfrom cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers\n\n\ndef load_pem_traditional_openssl_private_key(data, password, backend):\n    warnings.warn(\n        \"load_pem_traditional_openssl_private_key is deprecated and will be \"\n        \"removed in a future version, use load_pem_private_key instead.\",\n        utils.DeprecatedIn06,\n        stacklevel=2\n    )\n\n    return backend.load_traditional_openssl_pem_private_key(\n        data, password\n    )\n\n\ndef load_pem_pkcs8_private_key(data, password, backend):\n    warnings.warn(\n        \"load_pem_pkcs8_private_key is deprecated and will be removed in a \"\n        \"future version, use load_pem_private_key instead.\",\n        utils.DeprecatedIn06,\n        stacklevel=2\n    )\n\n    return backend.load_pkcs8_pem_private_key(data, password)\n\n\ndef load_pem_private_key(data, password, backend):\n    return backend.load_pem_private_key(data, password)\n\n\ndef load_pem_public_key(data, backend):\n    return backend.load_pem_public_key(data)\n\n\ndef load_ssh_public_key(data, backend):\n    key_parts = data.split(b' ')\n\n    if len(key_parts) != 2 and len(key_parts) != 3:\n        raise ValueError(\n            'Key is not in the proper format or contains extra data.')\n\n    key_type = key_parts[0]\n    key_body = key_parts[1]\n\n    try:\n        decoded_data = base64.b64decode(key_body)\n    except TypeError:\n        raise ValueError('Key is not in the proper format.')\n\n    if key_type == b'ssh-rsa':\n        return _load_ssh_rsa_public_key(decoded_data, backend)\n    elif key_type == b'ssh-dss':\n        return _load_ssh_dss_public_key(decoded_data, backend)\n    else:\n        raise UnsupportedAlgorithm(\n            'Only RSA and DSA keys are currently supported.'\n        )\n\n\ndef _load_ssh_rsa_public_key(decoded_data, backend):\n    key_type, rest = _read_next_string(decoded_data)\n    e, rest = _read_next_mpint(rest)\n    n, rest = _read_next_mpint(rest)\n\n    if key_type != b'ssh-rsa':\n        raise ValueError(\n            'Key header and key body contain different key type values.')\n\n    if rest:\n        raise ValueError('Key body contains extra bytes.')\n\n    return backend.load_rsa_public_numbers(RSAPublicNumbers(e, n))\n\n\ndef _load_ssh_dss_public_key(decoded_data, backend):\n    key_type, rest = _read_next_string(decoded_data)\n    p, rest = _read_next_mpint(rest)\n    q, rest = _read_next_mpint(rest)\n    g, rest = _read_next_mpint(rest)\n    y, rest = _read_next_mpint(rest)\n\n    if key_type != b'ssh-dss':\n        raise ValueError(\n            'Key header and key body contain different key type values.')\n\n    if rest:\n        raise ValueError('Key body contains extra bytes.')\n\n    parameter_numbers = DSAParameterNumbers(p, q, g)\n    public_numbers = DSAPublicNumbers(y, parameter_numbers)\n\n    return backend.load_dsa_public_numbers(public_numbers)\n\n\ndef _read_next_string(data):\n    \"\"\"Retrieves the next RFC 4251 string value from the data.\"\"\"\n    str_len, = struct.unpack('>I', data[:4])\n    return data[4:4 + str_len], data[4 + str_len:]\n\n\ndef _read_next_mpint(data):\n    \"\"\"\n    Reads the next mpint from the data.\n\n    Currently, all mpints are interpreted as unsigned.\n    \"\"\"\n    mpint_data, rest = _read_next_string(data)\n\n    return _int_from_bytes(mpint_data, byteorder='big', signed=False), rest\n\n\nif hasattr(int, \"from_bytes\"):\n    _int_from_bytes = int.from_bytes\nelse:\n    def _int_from_bytes(data, byteorder, signed=False):\n        assert byteorder == 'big'\n        assert not signed\n\n        if len(data) % 4 != 0:\n            data = (b'\\x00' * (4 - (len(data) % 4))) + data\n\n        result = 0\n\n        while len(data) > 0:\n            digit, = struct.unpack('>I', data[:4])\n            result = (result << 32) + digit\n            data = data[4:]\n\n        return result\n", "path": "src/cryptography/hazmat/primitives/serialization.py"}]}