Skip to content
shellhacks.dev
SSH and Networking

How to Verify SSH Host Key Fingerprints With Examples

Verify an SSH host key fingerprint before trusting a server: read it on the server, compare the prompt, and use console output, SSHFP DNS or certificates.

6 min read
Summarize in AI
Illustration for "How to Verify SSH Host Key Fingerprints With Examples": a shell script in an editor, a loop arrow, a padlock and key.

"The authenticity of host can't be established" is the prompt most people answer with yes without reading. The question is real: if an attacker sits between you and the server, that first answer decides whether your credentials reach them. Checking takes a minute when you know where to find the other copy of the fingerprint. This pairs with ssh-keyscan and known_hosts. The commands assume OpenSSH 10.0.

What the prompt shows

Shell
ssh [email protected]
Text
The authenticity of host 'web1.example.org (203.0.113.10)' can't be established.
ED25519 key fingerprint is SHA256:3f2a1c9d8b7e6a5f4c3b2a1908f7e6d5c4b3a291807f6.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

The line with SHA256: is the value to compare. Recent OpenSSH accepts the fingerprint itself as an answer instead of yes, which forces you to paste it and so to have it at hand. Older guides show an MD5 colon-separated form; ssh-keygen -l -E md5 prints that if you must compare against old records.

Get the other copy

Shell
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub -E sha256
for f in /etc/ssh/ssh_host_*_key.pub; do ssh-keygen -lf "$f"; done
Text
256 SHA256:3f2a1c9d8b7e6a5f4c3b2a1908f7e6d5c4b3a291807f6 root@web1 (ED25519)

Run this on the server through a trusted route: the provider's web console, a local terminal or a connection that already went through a verified key. The type in the prompt (ED25519 here) tells you which file to read. Cloud providers often print the fingerprints into the instance's console log at first boot; for AWS EC2 that is the system log, and others show them in the dashboard. Pre-publish the fingerprint in your inventory when you create the machine.

A picture helps

Shell
ssh -o VisualHostKey=yes [email protected]
ssh-keygen -lv -f /etc/ssh/ssh_host_ed25519_key.pub

The randomart image is a visual hash of the key, easier to compare at a glance than 43 characters of base64. It is an aid, not a stronger check. Many people compare the first and last few characters only, which is weaker than comparing the whole string; paste it into a diff or use grep -F to compare mechanically.

Remove the manual step

Shell
ssh-keygen -r web1.example.org
Text
web1.example.org IN SSHFP 4 2 3f2a1c9d8b7e...

This prints SSHFP resource records you can publish in DNS. With VerifyHostKeyDNS yes a client checks them, and it only means something if the zone is protected by DNSSEC; unsigned DNS can be spoofed as easily as the connection. A stronger option is a host certificate signed by your own authority, so every server's key is trusted through a single @cert-authority line, as in SSH certificates.

When the fingerprint changes

A warning that the key has changed is the case this matters for. After a planned rebuild, compare the new fingerprint as above before removing the old entry with ssh-keygen -R. If you did not change anything, treat it as a possible attack and stop. The meaning of that warning is in the identification-has-changed post, and the failure with strict checking in host key verification failed.

Where this does not apply

On a trusted local network with a server you just installed, the risk is low, and trust-on-first-use is the practical choice; it is still an assumption, not a check. Fleets should use certificates or pre-seeded known_hosts files in the image.

What the prompt is really asking

The message "The authenticity of host cannot be established" followed by a fingerprint and the question whether to continue appears the first time you connect to a host. It means the client has no recorded key for it, and is asking you to vouch for the key it was shown. The fingerprint is a hash of the host's public key, and it is shown in base64 with a SHA256: prefix in current versions, or as colon-separated hex in the older MD5 form, which you may meet in an old document or a provider console. Answering yes writes the key to your known hosts file, and from then on a different key produces a loud warning. Answering without comparing the fingerprint to a trusted source gives an attacker who is present at that moment a free pass, which is why careful teams record the fingerprints when servers are created, and check them on first contact.

Different key types have different fingerprints, and the prompt shows the one for the type negotiated. If your trusted copy is for another algorithm, the fingerprints will not match even though everything is fine, so compare like with like.

Getting the trusted copy

On the server, with console or existing access, print the fingerprint of each host key file with ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub, and likewise for the other types. Cloud providers often print the keys to the console log during the first boot, which you can read in the provider's interface or API, over an authenticated channel that does not depend on the network path to the server. For machines you build with provisioning tools, print the fingerprints as part of the run and store them. Display a picture of the key with the option VisualHostKey yes in the client configuration, which draws a small ASCII image that is easier to recognize than a string of characters, though it is only a memory aid. Where it is available, publish SSHFP records in a signed DNS zone, and set VerifyHostKeyDNS so the client checks them itself.

Removing the manual step safely

For fleets, the better answer is to remove the human decision. Host certificates signed by an internal CA let clients trust any server whose certificate the CA signed, with a single @cert-authority line in the known hosts file, and no per-host prompt. For smaller setups, distribute a verified known hosts file with your configuration management, so every client starts with the right keys. Avoid the shortcut of turning off strict checking, which gives up the protection entirely, and avoid sending the fingerprint by the same channel as the connection. When a fingerprint changes on a host you know, find out why: a reinstall, a restored image without the old keys, a changed load balancer, or an attack. Ask the administrator, compare with the console, and do not accept the new key until the change has an explanation.

Checking from the other direction

You can also verify from the client side without trusting the network path to the server you doubt. Connect from a second location, such as another network or a cloud shell, and compare the fingerprint it sees with the one on your first connection. A man in the middle is rarely present on two unrelated paths at once, so agreement is good evidence, and disagreement is a reason to stop. Use ssh-keyscan from both places and compare the output of ssh-keygen -lf on each. This does not replace a trusted record made at build time, and it is a useful extra check when no record exists and the situation is urgent.

See ssh-keygen(1) and RFC 4255 on SSHFP records.

Also inSecurity
Taggedssh
Share

Keep reading

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.