How to check ssh public key fingerprints?

The authenticity of host omecha.info (89.234.176.136)' can't be established.
ECDSA key fingerprint is SHA256:v7u4albDUtGH1EXWEwlt0KnzY9GDY5EqodUymKSbiSw
Are you sure you want to continue connecting (yes/no)? 

If you have ever used SSH, you have encountered this prompt. If you often SSH to new machines and you are like me, you probably type 'yes' without thinking about it.

In this article I describe how you can check your SSH fingerprints.

When you first connect to a remote server, SSH asks you if you accept the key fingerprint of the server. If you accept and choose to proceed, the public key of the server is added to your ~/.ssh/known_hosts. The next time you will connect to the server, SSH will check the public key sent by the server against the one in your known_hosts file. If it matches, the connection continue, if it doesn't match, it aborts with a big warning about a possible Man-in-the-Middle attack.

A Man-in-the-Middle attack happens when someone is intercepting your traffic to make you believe he is the server and to make the server believe he is you. The attackant does this by intercepting the public keys during the exchange when the connection is initiated and replace them with his own keys. From this point, the attackant is able to decrypt the traffic without your knowing.

To prevent this from happening, the fingerprint of the public key of the server is stored in your known_hosts file. But if the attackant is active during your first connection, it can screw you silently. So what can we do to avoid this?

We need to check the fingerprint of the server from another channel. This can be by right after the installation of a new server, by mailing the admin of the server (with GPG), over IRC/XMPP (with OTR), in person, etc.

If you are like me, you may know this but you never check the fingerprints because you don't remember the commands or didn't learn how to do it. But this days are over!

I am the admin of a server and have access to it. How to extract the fingerprint of my server?

The public keys of your server are stored in /etc/ssh/*.pub. Once you are logged on the server, you can use ssh-keygen -lf keyfile to get the fingerprint of the keys. For example :

ssh omecha.info ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub
256 SHA256:v7u4albDUtGH1EXWEwlt0KnzY9GDY5EqodUymKSbiSw root@omecha (ECDSA)

I don't have access to the server but I have already logged on the server. How to extract the fingerprint from my known_hosts file?

ssh-keygen -F "[omecha.info]:4422" -lf ~/.ssh/known_hosts
# Host [omecha.info]:4422 found: line 122 
[omecha.info]:4422 ECDSA SHA256:v7u4albDUtGH1EXWEwlt0KnzY9GDY5EqodUymKSbiSw 

As you can see, if the connection is on a non-standard port (not 22) you need to specify it.

How can I use ssh-keyscan to retrieve the fingerprint?

ssh-keyscan can be used to retrieve the public keys of a remote server.

ssh-keyscan -p 4422 omecha.info
[omecha.info]:4422 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXnLDXzI6NC9JMhwoh21ScP0HMQJ+JTnrH3y8Z0xTpgCmumydX6VPGxUyKCTM4BcZknT+qLF8yU3V9f5RVtnWaBPFZRtphWnZKDwuz9LbxUrF1mfrCeGkdjcbRilfmm0HRUrUppbr11E/aBTtyvzSGTZzp5RPeQkrxpwxyg7ILGCc4SsPUyytaRFPGwhRrvxt+Ehyi14O3KD9sKTX1ljfdy+xv+sPOFWLEqn4ShC+FUR/BlhchUiogiT4FEzuh0bOCD3PrYFSTHy6yCzDsIVKpP492XJxkpZsmj+fRWQxXQWUHCohBv1Vyy5aNe8ZR2N1B18I9qTLNrd/oZ2JxNyBh
[omecha.info]:4422 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIUUDeU3KZvURJ95eXHg0Ch/Fc2CXXHACdZRKxLBiB6UiCN24NeLy7wQF716pgsF0EoD4VPRmPmvzKnyGUQfo4=
[omecha.info]:4422 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKeq29Yg+6HFgzSK4OWUJSrCz8f5pXMguWYTtqQ1iRDW

You can use ssh-keygen to reformat the key.

ssh-keyscan -p 4422 omecha.info | ssh-keygen -lf -
256 SHA256:I0f3xfBvXlFqZZvsNMFYQVE2YHpqX3D6NRUhm5M0414 [omecha.info]:4422 (ED25519)
2048 SHA256:jTLBS3xUQN0vku3YrHOs00GsS3xXLdGKeQYAiOks2fc [omecha.info]:4422 (RSA)
256 SHA256:v7u4albDUtGH1EXWEwlt0KnzY9GDY5EqodUymKSbiSw [omecha.info]:4422 (ECDSA)

You can also do that "manually", one key at a time.

ssh-keyscan -t ecdsa -p 4422 omecha.info | cut -f 3 -d ' ' | base64 -d | sha256 -b
v7u4albDUtGH1EXWEwlt0KnzY9GDY5EqodUymKSbiSw=

With this, you can check the fingerprint of the server from a remote server (assuming you expect Man-in-the-Middle on your local network but not on your server).

ssh mysaferemote.net ssh-keyscan -p 4422 omecha.info | ssh-keygen -lf -
2048 SHA256:jTLBS3xUQN0vku3YrHOs00GsS3xXLdGKeQYAiOks2fc omecha.info (RSA)
256 SHA256:v7u4albDUtGH1EXWEwlt0KnzY9GDY5EqodUymKSbiSw omecha.info (ECDSA)
256 SHA256:I0f3xfBvXlFqZZvsNMFYQVE2YHpqX3D6NRUhm5M0414 omecha.info (ED25519)

You can do this over tor if you don't have another server or if you want a another confirmation.

torsocks ssh-keyscan -p 4422 89.234.176.136 | ssh-keygen -lf -
2048 SHA256:jTLBS3xUQN0vku3YrHOs00GsS3xXLdGKeQYAiOks2fc [89.234.176.136]:4422 (RSA)
256 SHA256:v7u4albDUtGH1EXWEwlt0KnzY9GDY5EqodUymKSbiSw [89.234.176.136]:4422 (ECDSA)
256 SHA256:I0f3xfBvXlFqZZvsNMFYQVE2YHpqX3D6NRUhm5M0414 [89.234.176.136]:4422 (ED25519)

SSH use hash format X and ssh-keygen format Y. How to change SSH/ssh-keygen hash function?

Use the option -E HASH with ssh-keygen or -o FingerPrintHash=HASH.

ssh -o FingerPrintHash=sha512 -o UserKnownHostsFile=/dev/null omecha.info
The authenticity of host '[omecha.info]:4422 ([89.234.176.136]:4422)' can't be established.
ECDSA key fingerprint is SHA512:R/1uH5ERkqP4gV7hEy9UI9J8oqhpAD3BD8XfTNGgrlTrH3MO+1Mg/rQal9gvPODoMfBGsqR0LksyWqh03b0Khw.
Are you sure you want to continue connecting (yes/no)?
ssh-keygen -E sha512 -F "[omecha.info]:4422" -lf ~/.ssh/known_hosts
# Host [omecha.info]:4422 found: line 122 
[omecha.info]:4422 ECDSA SHA512:R/1uH5ERkqP4gV7hEy9UI9J8oqhpAD3BD8XfTNGgrlTrH3MO+1Mg/rQal9gvPODoMfBGsqR0LksyWqh03b0Khw 

Conclusion

So we have seen various way to check the SSH fingerprint of a server. When you install a new server, I found that a good habit is to store the fingerprints in a trusted store (for example your password manager. This way, you have a trusted way to validate the fingerprint of your servers.

That's all folks!