Checking SSH host keys and their fingerprints
Saturday, 5 August 2023
Host keys are crucial to the security of SSH because they ensure that you are connecting to the server that you expect. This prevents a man in the middle (MITM) attack in which another server intercepts your connection. When you connect to a server for the first time, you're asked to check the host key. SSH prints the key fingerprint:
The authenticity of host '[address]' can't be established. ECDSA key fingerprint is SHA256:Ee41bYUsblt5XdmT+n/3DCoqq3zOkZkMl6CYLXSh1h8. Are you sure you want to continue connecting (yes/no/[fingerprint])?
When you connect for a second time, the host key is already known, and so the connection is automatic unless the host key has changed. In that case, SSH reports an error, and tells you the new fingerprint.
If SSH asks you about a key fingerprint, how can you know it is correct?
Fingerprints represent a key. They are normally shorter than the key itself, but should still identify it uniquely.
Unfortunately SSH software can display fingerprints in many different ways. What you see depends on three different things:
- What sort of key is used. By default, SSH servers have several host keys
with different types, e.g. RSA, ECDSA, and they are independent
so you can't check one using another. For example, here are three fingerprints for
different types of key on the same server:
RSA key fingerprint is SHA256:p7tA/SvUBkKFVswwK508U6QIywbHLFSS2mv1R89ao6k. ECDSA key fingerprint is SHA256:Ee41bYUsblt5XdmT+n/3DCoqq3zOkZkMl6CYLXSh1h8. ED25519 key fingerprint is SHA256:5+fUuRjulwPAhW1deYm8lsR015yqVgOod5AoRSN7r6M.
The hash algorithm used for fingerprinting. This could be SHA256 or MD5, or no hash
at all (in which case the public key is displayed). Here are three representations
of the same key, with different hash options:
256 MD5:4e:4d:2c:72:91:fe:a1:6f:47:45:3d:e6:4a:1f:76:bd [address] (ED25519) 256 SHA256:5+fUuRjulwPAhW1deYm8lsR015yqVgOod5AoRSN7r6M [address] (ED25519) [Not hashed] AAAAC3NzaC1lZDI1NTE5AAAAIHwjzLHwCMfAcAcEr+PrLT4OFsoPfuyv71zrI2TULNDH
The user interface of the SSH software. Sometimes a "randomart" image may be used.
Here are two representations of the same fingerprint:
256 MD5:4e:4d:2c:72:91:fe:a1:6f:47:45:3d:e6:4a:1f:76:bd [address] (ED25519) +--[ED25519 256]--+ | .. . | | .o .o.| | ..o o .o o| | o.+. ..+o| | So....+ +| | o. . .. E | | .. . | | o . | | . . | +------[MD5]------+
As there can be three or four different host key types (RSA, ECDSA, ED25519 and sometimes DSA), at least three different fingerprint hashes (SHA256, MD5 and not hashed), and at least two ways to represent the fingerprint, a direct comparison may be difficult.
Forcing the use of a particular host key
If you've never logged into the server, but you already know the fingerprint for one host key type, then you can force SSH to use that key type for the connection.
This is useful if you have been given a correct fingerprint by some other means. For example, you might be a Github user, and you're looking at their list of key fingerprints, or something similar elsewhere.
To use a particular key type, you need to know the internal name for the algorithm:
- For ECDSA, use ssh -o HostKeyAlgorithms=ecdsa-sha2-nistp256
- For ED25519, use ssh -o HostKeyAlgorithms=ssh-ed25519
- For RSA, use ssh -o HostKeyAlgorithms=rsa-sha2-256
- For RSA, if the server is running old SSH software, you might need ssh -o HostKeyAlgorithms=ssh-rsa
You can also specify the hash function for the fingerprint, if you only know the MD5 fingerprint, e.g. -o FingerprintHash=md5.
The -o VisualHostKey=yes option will show a "randomart" image. I don't know of a way to show the public key without a fingerprint hash with SSH itself, but debugging options might allow for this.
Checking the fingerprint on the server
If you can log in to the server already, e.g. from an SSH client that already knows one of the key fingerprints, then you can get all of the possible fingerprints directly from the key files. The following commands will work with typical configurations of OpenSSH. Enter:
cat /etc/ssh/*pub | ssh-keygen -lf -
This prints out the fingerprint for each host key. However, it will only be printed using one hash algorithm: by default, SHA256. If you would like to see MD5 hashes instead, you can use the -E option like this:
cat /etc/ssh/*pub | ssh-keygen -lf - -E md5
If you would like to see "randomart" images, use -v, and if you would like to see the public keys without any hashing, then you can just use:
Looking at SSH's "known_hosts" file
SSH remembers host keys in the "known_hosts" file which you can find in the .ssh subdirectory within your home directory.
If your connections to the server don't allow you to enter commands, but you have previously connected to the server, you can find the host key fingerprint using:
ssh-keygen -F [address] -l
Add -E md5 to see the MD5 fingerprint, and remove -l to see the entire key.
Checking "known_hosts" can also be useful if you accept a host key without properly examining it. To remove a host key, you can use the -R option.
"known_hosts" can sometimes be edited directly, but usually the host names are hashed in order to make it more difficult for an attacker to find a list of other machines that a key may also have access to.
For PuTTY users
In PuTTY, your first connection to a new server opens a dialog box with the fingerprint, represented as a SHA256 fingerprint. The "More Info..." button shows the same host key without hashing and with an MD5 fingerprint.
If you would like to see a different host key, then the Connection → SSH → Host keys configuration page allows you to prioritise particular algorithms for the host key. Move the preferred host key type to the top of the list.
After connecting, fingerprints can also be seen in the Event Log which is accessible by clicking in the top left corner of the PuTTY window.
PuTTY's "Special Commands" menu includes an option to upgrade the host key type while connected. You can use this to install additional host keys. This feature is accessible via the top left menu.
The different possibilities exist because algorithms can become deprecated if their security is questioned. Therefore, the SSH protocol is extensible so that new algorithms can be added and old ones can become optional and eventually be removed. MD5 is now considered insecure, DSA has been deprecated, and while RSA itself is fine, the ssh-rsa host key algorithm is considered insecure because it relies on SHA1. The newer rsa-sha2-256 algorithm does not have this issue. More changes are likely in the future, so there may be more types of host key and more types of fingerprint by the time you read this.