SSH Key Fingerprints: Generation and Verification
When connecting to a remote host via SSH, you might encounter a warning like this:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:sYNNR1L6T5cSAG4BndqtdDhJEI0eB9LamBTkuIue3+0.
Please contact your system administrator.
Add correct host key in /Users/xx/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /Users/xx/.ssh/known_hosts:40
ECDSA host key for [xx.com] has changed and you have requested strict checking.
Host key verification failed.
This warning signals a potential man-in-the-middle (MITM) attack—the remote host’s public key differs from the one stored local.
When connecting to a host for the first time, you’ll see a prompt like:
The authenticity of host [xx.com] can't be established.
ECDSA key fingerprint is SHA256:/FtMoqIv9WakAZklbpVU9pmlsgVt5pEQCAMrJLj8Zp8.
Are you sure you want to continue connecting (yes/no)?
Most users type yes (similar to accepting software prompts). This adds the server’s SSH public key to ~/.ssh/known_hosts.
What is a Key Fingerprint?
A key fingerprint is a human-readable hash (e.g., SHA256, MD5) of a public key. It simplifies verifying the key’s identity without sharing the full key.
Generating a Key Fingerprint
1. From a Local Public Key
Use ssh-keygen to generate a fignerprint from a local public key (e.g., /etc/ssh/ssh_host_rsa_key.pub):
$ cd /etc/ssh/
$ ssh-keygen -lf ssh_host_rsa_key.pub
2048 SHA256:mDeLabzTVsvlIZp4aYjE1z4kPU2N9l0fpnKGVX3Xlko root@example (RSA)
To use a different hash algorithm (e.g., MD5):
$ ssh-keygen -E md5 -lf ssh_host_ecdsa_key.pub
256 MD5:b9:9c:c6:c1:53:8e:7b:81:75:9d:96:6c:a4:3a:8c:62 root@example (ECDSA)
2. From a Remote Host (via ssh-keyscan)
Retrieve the remote host’s public key and generate its fingerprint in one step:
$ ssh-keyscan testserver.com | ssh-keygen -lf -
# testserver.com:22 SSH-2.0-OpenSSH_8.2
testserver.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD... (truncated)
2048 SHA256:abcdefghijklmnopqrstuvwxyz1234567890 testserver.com (RSA)
To target a specific key type (e.g., ECDSA):
$ ssh-keyscan -t ecdsa testserver.com | ssh-keygen -lf -
# testserver.com:22 SSH-2.0-OpenSSH_8.2
testserver.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYT... (truncated)
256 SHA256:1234567890abcdefghijklmnopqrstuvwxyz testserver.com (ECDSA)
Veirfying Key Fingerprints
To confirm a remote host’s identity, compare fingerprints from two sources (e.g., the server administrator’s provided fingerprint vs. the one you retrieve via ssh-keyscan).
Example: Verify an ECDSA Fingerprint
- Server-side (trusted environment): Generate the fingerprint from the server’s public key:
$ ssh-keygen -E sha256 -lf /etc/ssh/ssh_host_ecdsa_key.pub
256 SHA256:QUfCwW6Br5EwwESsulN2TEidBoDNca888RNflZG++bI root@localhost (ECDSA)
- Client-side (remote retrieval): Fetch the fingerprint over the network:
$ ssh-keyscan -t ECDSA -p 22 127.0.0.1 2>/dev/null | ssh-keygen -E sha256 -lf -
256 SHA256:QUfCwW6Br5EwwESsulN2TEidBoDNca888RNflZG++bI 127.0.0.1 (ECDSA)
If the fingerprints match, the public key is authentic.
Underlying Principle
The fingerprint is derived by hashing the public key (e.g., with SHA256 or MD5). A tiny change in the key (even a single bit) produces a drastically different fingerprint, detecting tampering.
Bonus: Fingerprint During Key Pair Generation
When creating an SSH key pair with ssh-keygen, the fingerprint is displayed:
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/user/.ssh/id_rsa): my_key
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in my_key.
Your public key has been saved in my_key.pub.
The key fingerprint is:
SHA256:Bw1NuIXaa7h6tzABTDOq0/esnqQiNJe4FeNThfYffHY user@local
The key's randomart image is:
+---[RSA 2048]----+
| .=.+ |
| . ooo |
| o +.o. |
| .o+ +S |
| .o+. oS+.o E |
| o..+=..+.+ . |
|o.o+. *o . |
|*.ooo+oo.o= |
|==.o==o...= |
+----[SHA256]-----+
Advanced: Manual Fingerprint Calculation
To see how the fingerprint is generated, decode the base64-encoded public key and hash it:
Local Public Key
$ awk '{print $2}' ssh_host_ecdsa_key.pub | base64 -d | shasum -a 256 -b | awk '{print $1}' | xxd -r -p | base64
fMVRWYO/+73I9ZoFGhPKelH67IoPyexzLBtbxUx2EhE=
Remote Public Key
$ ssh-keyscan -t ecdsa 192.168.10.1 | awk '{print $3}' | base64 -d | openssl sha256 -binary | base64
# 192.168.10.1:22 SSH-2.0-OpenSSH_7.4p1
fMVRWYO/+73I9ZoFGhPKelH67IoPyexzLBtbxUx2EhE=
Batch Processing (Optional)
To generate fingerprints for all public keys in /etc/ssh/:
SHA1 Fingerprints
for key in /etc/ssh/*key.pub; do
ssh-keygen -E sha1 -lf "$key"
done
MD5 Fingerprints
for key in /etc/ssh/*key.pub; do
ssh-keygen -E md5 -lf "$key"
done