1commit 46d08c8eefc18d22e9d893a627cc6d73b43cdb9a
2Author: Martin Weinelt <hexa@gaia.lossy.network>
3Date: Mon Aug 11 00:48:21 2025 +0200
4
5 sshtunnel: remove DSA support
6
7 The support for DSA keys was removed[1] in Paramiko 4.0.
8
9 [1] https://www.paramiko.org/changelog.html#4.0.0
10
11diff --git a/README.rst b/README.rst
12index 7400816..ff27733 100644
13--- a/README.rst
14+++ b/README.rst
15@@ -255,9 +255,9 @@ CLI usage
16 -k SSH_HOST_KEY, --ssh_host_key SSH_HOST_KEY
17 Gateway's host key
18 -K KEY_FILE, --private_key_file KEY_FILE
19- RSA/DSS/ECDSA private key file
20+ RSA/ECDSA private key file
21 -S KEY_PASSWORD, --private_key_password KEY_PASSWORD
22- RSA/DSS/ECDSA private key password
23+ RSA/ECDSA private key password
24 -t, --threaded Allow concurrent connections to each tunnel
25 -v, --verbose Increase output verbosity (default: ERROR)
26 -V, --version Show version number and quit
27diff --git a/sshtunnel.py b/sshtunnel.py
28index c48e330..e6442da 100644
29--- a/sshtunnel.py
30+++ b/sshtunnel.py
31@@ -1090,7 +1090,6 @@ class SSHTunnelForwarder(object):
32 host_pkey_directories = [DEFAULT_SSH_DIRECTORY]
33
34 paramiko_key_types = {'rsa': paramiko.RSAKey,
35- 'dsa': paramiko.DSSKey,
36 'ecdsa': paramiko.ECDSAKey}
37 if hasattr(paramiko, 'Ed25519Key'):
38 # NOQA: new in paramiko>=2.2: http://docs.paramiko.org/en/stable/api/keys.html#module-paramiko.ed25519key
39@@ -1286,7 +1285,7 @@ class SSHTunnelForwarder(object):
40
41 Arguments:
42 pkey_file (str):
43- File containing a private key (RSA, DSS or ECDSA)
44+ File containing a private key (RSA or ECDSA)
45 Keyword Arguments:
46 pkey_password (Optional[str]):
47 Password to decrypt the private key
48@@ -1295,7 +1294,7 @@ class SSHTunnelForwarder(object):
49 paramiko.Pkey
50 """
51 ssh_pkey = None
52- key_types = (paramiko.RSAKey, paramiko.DSSKey, paramiko.ECDSAKey)
53+ key_types = (paramiko.RSAKey, paramiko.ECDSAKey)
54 if hasattr(paramiko, 'Ed25519Key'):
55 # NOQA: new in paramiko>=2.2: http://docs.paramiko.org/en/stable/api/keys.html#module-paramiko.ed25519key
56 key_types += (paramiko.Ed25519Key, )
57@@ -1805,7 +1804,7 @@ def _parse_arguments(args=None):
58 dest='ssh_private_key',
59 metavar='KEY_FILE',
60 type=str,
61- help='RSA/DSS/ECDSA private key file'
62+ help='RSA/ECDSA private key file'
63 )
64
65 parser.add_argument(
66@@ -1813,7 +1812,7 @@ def _parse_arguments(args=None):
67 dest='ssh_private_key_password',
68 metavar='KEY_PASSWORD',
69 type=str,
70- help='RSA/DSS/ECDSA private key password'
71+ help='RSA/ECDSA private key password'
72 )
73
74 parser.add_argument(
75diff --git a/tests/test_forwarder.py b/tests/test_forwarder.py
76index 40662d0..02af175 100644
77--- a/tests/test_forwarder.py
78+++ b/tests/test_forwarder.py
79@@ -81,11 +81,9 @@ open_tunnel = partial(
80
81 SSH_USERNAME = get_random_string()
82 SSH_PASSWORD = get_random_string()
83-SSH_DSS = b'\x44\x78\xf0\xb9\xa2\x3c\xc5\x18\x20\x09\xff\x75\x5b\xc1\xd2\x6c'
84 SSH_RSA = b'\x60\x73\x38\x44\xcb\x51\x86\x65\x7f\xde\xda\xa2\x2b\x5a\x57\xd5'
85 ECDSA = b'\x25\x19\xeb\x55\xe6\xa1\x47\xff\x4f\x38\xd2\x75\x6f\xa5\xd5\x60'
86 FINGERPRINTS = {
87- 'ssh-dss': SSH_DSS,
88 'ssh-rsa': SSH_RSA,
89 'ecdsa-sha2-nistp256': ECDSA,
90 }
91@@ -1202,7 +1200,7 @@ class AuxiliaryTest(unittest.TestCase):
92 '-P={0}'.format(SSH_PASSWORD), # GW password
93 '-R', '10.0.0.1:8080', '10.0.0.2:8080', # remote bind list
94 '-L', ':8081', ':8082', # local bind list
95- '-k={0}'.format(SSH_DSS), # hostkey
96+ '-k={0}'.format(SSH_RSA), # hostkey
97 '-K={0}'.format(__file__), # pkey file
98 '-S={0}'.format(SSH_PASSWORD), # pkey password
99 '-t', # concurrent connections (threaded)
100@@ -1232,7 +1230,7 @@ class AuxiliaryTest(unittest.TestCase):
101 '--password={0}'.format(SSH_PASSWORD), # GW password
102 '--remote_bind_address', '10.0.0.1:8080', '10.0.0.2:8080',
103 '--local_bind_address', ':8081', ':8082', # local bind list
104- '--ssh_host_key={0}'.format(SSH_DSS), # hostkey
105+ '--ssh_host_key={0}'.format(SSH_RSA), # hostkey
106 '--private_key_file={0}'.format(__file__), # pkey file
107 '--private_key_password={0}'.format(SSH_PASSWORD),
108 '--threaded', # concurrent connections (threaded)
109@@ -1254,7 +1252,7 @@ class AuxiliaryTest(unittest.TestCase):
110 [('10.0.0.1', 8080), ('10.0.0.2', 8080)])
111 self.assertListEqual(parser['local_bind_addresses'],
112 [('', 8081), ('', 8082)])
113- self.assertEqual(parser['ssh_host_key'], str(SSH_DSS))
114+ self.assertEqual(parser['ssh_host_key'], str(SSH_RSA))
115 self.assertEqual(parser['ssh_private_key'], __file__)
116 self.assertEqual(parser['ssh_private_key_password'], SSH_PASSWORD)
117 self.assertTrue(parser['threaded'])