Many people using recent versions of ssh are now seeing SHA256 fingerprints by default when connecting to a new server, and finding it difficult to verify the fingerprint because the server itself doesn’t seem to have the right versions to tell you!
For example, here’s the client trying to connect …
$ ssh galathilion The authenticity of host 'galathilion (10.30.64.220)' can't be established. RSA key fingerprint is SHA256:8DpA4frlTxKnZ5GJXkORq8QQlLn4eCx4nZf51g55vYc.
The correct thing to do here is to check this fingerprint, by connecting to the target server over something that isn’t ssh. Then you run the ssh-keygen command to see the fingerprint …
# ssh-keygen -lf /etc/ssh/ssh_host_rsa_key 2048 d3:c6:fa:83:03:f4:ed:44:a4:3e:80:e1:b1:7b:ca:42 /etc/ssh/ssh_host_rsa_key.pub (RSA)
But that’s the wrong format – the MD5 version of the fingerprint, not the SHA256 version. That’s probably because the server version of the openssh tools doesn’t support SHA256 at all. And you can’t work out what the SHA256 fingerprint will be if all you have is the MD5 fingerprint data.
No problem; you can just ask your client ssh to display the server’s fingerprint using the old MD5 presentation :-
$ ssh -o FingerprintHash=md5 galathilion The authenticity of host 'galathilion (10.30.64.220)' can't be established. RSA key fingerprint is MD5:d3:c6:fa:83:03:f4:ed:44:a4:3e:80:e1:b1:7b:ca:42.
So that works a treat, and you can validate the connection. Regardless of the scheme used to present the fingerprint to you, it’s the same server public key, so validating the MD5 presentation is the same as validating the SHA256 version.
As an alternative, you can use standard command-line tools to generate the SHA256 fingerprint on the server itself, even though openssh doesn’t do that for you.
# cat /etc/ssh/ssh_host_rsa_key.pub \ | awk '{print $2}' | base64 -d | sha256sum -b \ | awk '{print $1}' | xxd -r -p | base64 8DpA4frlTxKnZ5GJXkORq8QQlLn4eCx4nZf51g55vYc=
That mouthful produces the same output as the openssh tool.
Here’s a worked-through example of how this command chain works. I can reproduce the original machine’s data here, because this is a public key. Remember to carefully check what data you are publishing online!
# cat /etc/ssh/ssh_host_rsa_key.pub ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA3R3I0dJxyg61jKuAqY3wJ/gwHzzEVg73sVqqJnzzEGWEkpjEYsIBk1NWh/Ur2q9CnR1KPk8Av22fNgeQay6dm9FcGK7TImiD3ZZfZjfHPzwkcoXyQPuJHW9pT8rlktkihdpTNJqlHHibVUz481AntmptypGqPKdg22EjvjrHk5Q4Op/ahZjgkSoFPphH1gWZcCC2xSPi/mk6nu9DF4Jyr1dJq+hJMPuvQ10ozOpzhemUKD9dGoXIh9g78/+M9Y8/naOW+UxZAy8BGrcpjM27sLHU0K+qxLRFw36Xlgur2+lEiSVt0F2iPpbAiJug3hUQTx2K3gkMG36auVsgrWvK9Q==
This file has a single line, with two (or three) values space-separated. The second field is the Base64 representation of the public key itself, which we’re extracting using awk '{print $2}' (although we could have done this with other commands, such as cut -d' ' -f2). Once we have that field, we convert it from Base64 back into raw binary with base64 -d. Then we pass the binary key through sha256sum, which will produce two fields, a hex-encoded fingerprint and the filename (which is just ‘-‘ for standard input), and through awk again to select just the first field. xxd is used to convert the hex-encoded data back to binary again, and finally base64 gives us the same encoding that the openssh tools present.
Why bother with all that? Well, remember that the requirement to verify a server’s ssh fingerprint should not be carried out over ssh itself. I get my servers to write their ssh fingerprints into the /etc/issue file, and this is displayed on the server console by default along with the login prompt. So I can always validate the ssh keys using something that isn’t ssh …