
SSH Key Fingerprints
Photo Credits: Unsplash
Introduction
I recently tried to match my local SSH key pairs with SSH keys I had registered on my Github account. Github displays the fingerprint of each uploaded key (see header image), so naturally, I tried to fingerprint my locally-stored keys for comparison. It was not as straightforward as I thought (though it could have been - see the final section of this article for the easy, "right" way of doing this).
Here's what I learned about the SSH key fingerprinting process:
Generating a Fingerprint from an SSH Pubkey
To generate an SSH key fingerprint, run the following command(s):
KEYFILE=/tmp/tmpkey.pub # replace with your own
grep -oE 'AAAA\S+' $KEYFILE | base64 -d | sha256sum | cut -d ' ' -f 1 | xxd -r -p | base64
Brief Explanation
- Get the key "blob"
- Decode from base64 and hash the raw bytes
- Convert the hex-encoded hash into a base64-encoded hash
Detailed Explanation
grep -oE 'AAAA\S+' $KEYFILE | base64 -d
The 'middle part' of an SSH public key file contains base64-encoded data.
- The exact layout of the encoded data varies by key type
- All key types start with a 'key type' string, where the string representation (and all data type representations) should comply with RFC 4251, Section 5
- Per RFC 4251, strings start with a UINT32 (4-byte integer) that specifies how long the string will be
- That's why we can reliably
grep
for 4x 'A' characters - the first three bytes of the encoded data are effectively guaranteed to be null.
- That's why we can reliably
- Once the key type is known, the key is parsed according to its format. For example, the ssh-ed25519 format is defined here; 'ssh-rsa' and some other common types are defined in Section 6.6 of RFC 4253
- For further reading
sha256sum | cut -d ' ' -f 1
- Regardless of key type and encoded-data layout, SSH fingerprints are based on the hash of all bits in the 'base64' section
sha256sum
outputs the hash plus a trailing filename and newline, hence thecut
command- Sidenote: a (rejected) proposal to add a hash-only output format to
sha256sum
- Sidenote: a (rejected) proposal to add a hash-only output format to
xxd -r -p | base64
- Just like an encryption key, a sha256 hash is a series of bits, not human-readable characters. Hashes tend to be displayed as either hex or base64-encoded strings for human consumption.
sha256sum
outputs a hex-encoded string; SSH fingerprints are typically displayed as base64-encoded strings
The 'Right' Way
ssh-keygen
outputs a key's fingerprint when first generated; It can also output the fingerprint of an existing public key file with ssh-keygen -lf PATH_TO_KEYFILE
. (I was unaware of this when first going down the rabbit-hole from which this post was created.)