diff options
author | Jeff Forcier <jeff@bitprophet.org> | 2023-04-14 14:48:01 -0400 |
---|---|---|
committer | Jeff Forcier <jeff@bitprophet.org> | 2023-05-05 12:26:56 -0400 |
commit | 57c33481fda5cd9338df2bb4d5c090f50bcc7343 (patch) | |
tree | bab08143b210da992e8ebe89e9386b0b01a1ceaa | |
parent | 80556bdc9944df60eb0a06c3985bcf2dae1376e2 (diff) |
Add new PKey.fingerprint property at long last
-rw-r--r-- | paramiko/pkey.py | 17 | ||||
-rw-r--r-- | sites/www/changelog.rst | 5 | ||||
-rw-r--r-- | tests/test_pkey.py | 10 |
3 files changed, 31 insertions, 1 deletions
diff --git a/paramiko/pkey.py b/paramiko/pkey.py index cbb5b3ff..f8878be3 100644 --- a/paramiko/pkey.py +++ b/paramiko/pkey.py @@ -24,7 +24,7 @@ import base64 from base64 import encodebytes, decodebytes from binascii import unhexlify import os -from hashlib import md5 +from hashlib import md5, sha256 import re import struct @@ -169,6 +169,21 @@ class PKey: """ return md5(self.asbytes()).digest() + @property + def fingerprint(self): + """ + Modern fingerprint property designed to be comparable to OpenSSH. + + Currently only does SHA256 (the OpenSSH default). + + .. versionadded:: 3.2 + """ + hashy = sha256(bytes(self)) + hash_name = hashy.name.upper() + b64ed = encodebytes(hashy.digest()) + cleaned = u(b64ed).strip().rstrip("=") # yes, OpenSSH does this too! + return f"{hash_name}:{cleaned}" + def get_base64(self): """ Return a base64 string containing the public part of this key. Nothing diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst index d93c0494..8ff9f179 100644 --- a/sites/www/changelog.rst +++ b/sites/www/changelog.rst @@ -2,6 +2,11 @@ Changelog ========= +- :feature:`-` `~paramiko.pkey.PKey` grew a new ``.fingerprint`` property which + emits a fingerprint string matching the SHA256+Base64 values printed by + various OpenSSH tooling (eg ``ssh-add -l``, ``ssh -v``). This is intended to + help troubleshoot Paramiko-vs-OpenSSH behavior and will eventually replace + the venerable ``get_fingerprint`` method. - :bug:`-` `~paramiko.agent.AgentKey` had a dangling Python 3 incompatible ``__str__`` method returning bytes. This method has been removed, allowing the superclass' (`~paramiko.pkey.PKey`) method to run instead. diff --git a/tests/test_pkey.py b/tests/test_pkey.py index 4d74d8aa..477da0e3 100644 --- a/tests/test_pkey.py +++ b/tests/test_pkey.py @@ -643,6 +643,16 @@ class KeyTest(unittest.TestCase): for key1, key2 in self.keys(): assert hash(key1) == hash(key2) + def test_new_fingerprint(self): + # Assumes the RSA, DSS, ECDSA, Ed25519 order seen in 'def keys'. + fingerprints = [x.fingerprint for x, _ in self.keys()] + assert fingerprints == [ + "SHA256:OhNL391d/beeFnxxg18AwWVYTAHww+D4djEE7Co0Yng", + "SHA256:uHwwykG099f4M4kfzvFpKCTino0/P03DRbAidpAmPm0", + "SHA256:BrQG04oNKUETjKCeL4ifkARASg3yxS/pUHl3wWM26Yg", + "SHA256:J6VESFdD3xSChn8y9PzWzeF+1tl892mOy2TqkMLO4ow", + ] + def test_ed25519_nonbytes_password(self): # https://github.com/paramiko/paramiko/issues/1039 Ed25519Key.from_private_key_file( |