Regis May
Regis May

Reputation: 3466

How to calculate a fingerprint from an RSA public key?

With this command it is possible to generate an RSA public-private key pair:

ssh-keygen -f key

Now I would like to load these keys in Python using module cryptography. Example:

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization

with open("key.pub", "rb") as f:
    datapub = f.read()

public_key = serialization.load_ssh_public_key(datapub, backend=default_backend())

But now: How do you generate a fingerprint from this public key? With OpenSSH this can be done using ssh-keygen -lf key.pub. But how do you the same in Python?

Upvotes: 0

Views: 2766

Answers (1)

Regis May
Regis May

Reputation: 3466

First of all: Thank you very much Topaco, you provided the essential hint to me how to generate such a fingerprint. I crosschecked this with other sources on the WWW and can no provide code for anybody to use.

Let's assume we've loaded the key and stored it in public_key. Then a fingerprint can be generated as follows:

rawKeyData = public_key.public_bytes(
    encoding=serialization.Encoding.OpenSSH,
    format=serialization.PublicFormat.OpenSSH,
)

# prepare for hashing
m = re.match("ssh-rsa ([A-Za-z0-9+/=]+)", rawKeyData.decode("utf-8"))
assert m is not None
base64BinaryData = m.group(1).encode("utf-8")
rawBinaryData = base64.b64decode(base64BinaryData)

# now create the hash
hexDigest = hashlib.md5(rawBinaryData).hexdigest()

# formatting for output similar to "ssh-keygen -l -E md5 -f <pubkeyfile>"
chunks = [ hexDigest[i:i+2] for i in range(0, len(hexDigest), 2) ]
fingerprint = str(self.__public_key.key_size) + "MD5:" + ":".join(chunks) + " (RSA)"

This provides output like this:

2048 MD5:bd:5a:67:a3:4c:46:9d:2c:63:78:7e:68:bc:82:eb:23 (RSA)

The only difference to OpenSSH fingerprints: Here no email address is included in the output.

Some remarks:

  • regex
    • I use a regular expression here to parse the output. This is done for safety as this way I ensure that the output matches the expectations of data processing here.
  • base64
    • base64 might add padding to the data.
    • base64 is safe to use as padding is deterministic.
  • md5
    • Here the MD5 output is used.
    • You can safely replace MD5 by any other hash algorithm if you want - e.g. SHA256.

Upvotes: 0

Related Questions