Skip to content

Commit

Permalink
Merge pull request #110 from ploxiln/prep_288
Browse files Browse the repository at this point in the history
prepare for release 2.8.8
  • Loading branch information
ploxiln authored Dec 1, 2021
2 parents 78fb9f0 + 2ca9cef commit 3297fb3
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 20 deletions.
2 changes: 1 addition & 1 deletion paramiko/_version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# last version component is odd for pre-release development, even for stable release
__version_info__ = (2, 8, 7)
__version_info__ = (2, 8, 8)
__version__ = '.'.join(map(str, __version_info__))
1 change: 1 addition & 0 deletions paramiko/hostkeys.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ def __delitem__(self, key):
for e in list(self._entries):
if e.key.get_name() == key:
self._entries.remove(e)
break
else:
raise KeyError(key)

Expand Down
20 changes: 7 additions & 13 deletions paramiko/pkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,26 +209,20 @@ def asbytes(self):
def __str__(self):
return self.asbytes()

# noinspection PyUnresolvedReferences
# TODO: The comparison functions should be removed as per:
# https://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons
def __cmp__(self, other):
# python-2 only, same purpose as __eq__()
return cmp(self.asbytes(), other.asbytes()) # noqa

def __eq__(self, other):
"""
Compare this key to another. Returns 0 if this key is equivalent to
the given key, or non-0 if they are different. Only the public parts
Compare this key to another. Returns True if this key is equivalent to
the given key, or False if they are different. Only the public parts
of the key are compared, so a public key will compare equal to its
corresponding private key.
:param .PKey other: key to compare to.
"""
hs = hash(self)
ho = hash(other)
if hs != ho:
return cmp(hs, ho) # noqa
return cmp(self.asbytes(), other.asbytes()) # noqa

def __eq__(self, other):
return hash(self) == hash(other)
return self.asbytes() == other.asbytes()

def get_name(self):
"""
Expand Down
11 changes: 8 additions & 3 deletions paramiko/rsakey.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,15 @@ def verify_ssh_sig(self, data, msg):
if isinstance(key, rsa.RSAPrivateKey):
key = key.public_key()

# pad received signature with leading zeros, key.verify() expects
# a signature of key_size bits (e.g. PuTTY doesn't pad)
sign = msg.get_binary()
diff = key.key_size - len(sign) * 8
if diff > 0:
sign = b"\x00" * ((diff + 7) // 8) + sign

try:
key.verify(
msg.get_binary(), data, padding.PKCS1v15(), hashes.SHA1()
)
key.verify(sign, data, padding.PKCS1v15(), hashes.SHA1())
except InvalidSignature:
return False
else:
Expand Down
8 changes: 5 additions & 3 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,15 +409,17 @@ def test_cleanup(self):
self.tc.close()
del self.tc

# force a collection to see whether the SSHClient object is deallocated
# 2 GCs are needed on PyPy, time is needed for Python 3
# GC is unpredictable, depending on python version and implementation
time.sleep(0.1)
gc.collect()
time.sleep(0.2)
gc.collect()
time.sleep(0.1)
gc.collect()
time.sleep(0.2)
gc.collect()
time.sleep(0.1)
gc.collect()

self.assertTrue(p() is None)

def test_client_can_be_used_as_context_manager(self):
Expand Down
17 changes: 17 additions & 0 deletions tests/test_hostkeys.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,20 @@ def test_delitem(self):
pass # Good
else:
assert False, "Entry was not deleted from HostKeys on delitem!"

def test_entry_delitem(self):
hostdict = paramiko.HostKeys('hostfile.temp')
target = 'happy.example.com'
entry = hostdict[target]
key_type_list = [key_type for key_type in entry]
for key_type in key_type_list:
del entry[key_type]

# will KeyError if not present
for key_type in key_type_list:
try:
del entry[key_type]
except KeyError:
pass # Good
else:
assert False, "Key was not deleted from Entry on delitem!"
19 changes: 19 additions & 0 deletions tests/test_pkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,25 @@ def test_certificates(self):
_support('test_rsa.key-cert.pub'),
)

def keys_loaded_twice(self):
for key_class, filename in [
(RSAKey, "test_rsa.key"),
(DSSKey, "test_dss.key"),
(ECDSAKey, "test_ecdsa_256.key"),
(Ed25519Key, "test_ed25519.key"),
]:
key1 = key_class.from_private_key_file(_support(filename))
key2 = key_class.from_private_key_file(_support(filename))
yield key1, key2

def test_keys_are_comparable(self):
for key1, key2 in self.keys_loaded_twice():
assert key1 == key2

def test_keys_are_hashable(self):
for key1, key2 in self.keys_loaded_twice():
assert hash(key1) == hash(key2)

def test_autodetect_ed25519(self):
key = load_private_key_file(_support("test_ed25519.key"))
self.assertIsInstance(key, Ed25519Key)
Expand Down

0 comments on commit 3297fb3

Please sign in to comment.