Verifying SSH Host Fingerprints

If you use ssh you’re familiar with this message:

~$ ssh rich.elharo.com
The authenticity of host 'rich.elharo.com (192.168.254.36)' can't be established.
RSA key fingerprint is 5a:65:0f:5f:21:bb:fd:6a:5a:68:cd:62:58:5d:fb:9f.
Are you sure you want to continue connecting (yes/no)?

If you’re like me, you regularly just type yes and continue without much thought:

Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added ‘rich.elharo.com,192.168.254.36’ (RSA) to the list of known hosts.

But is that really safe? Probably. The actual chance that a man-in-the-middle attack is being attempted is quite small. Even the FBI prefers breaking and entering to implementing a man-in-the-middle attack. Possibly the NSA might try it–I don’t know–but most of the time when I’m warned that a key has changed it’s after the server hardware has been upgraded, the operating system reinstalled, or some other major change made. However, recently I was hit with this message when connecting between two of my own machines on which nothing appeared to have changed, so I decided to be more than usually paranoid and actually verify the communication. That’s when it hit me: how do you do this? Where can you find the remote system’s key to compare it to the one you see on the client?

First a little terminology. The actual server key is a long stream of letters and numbers. Here’s one key:

AAAAB3NzaC1yc2EAAAABIwAAAIEAvVf59KxAmBqw
nuiam0wzBdNWzocaFTwQCLXpPlhfA1weLcfdSjzopGP
pXd1NoYKz2OAiWSKkg0nb9al1XDMPbJm54ZtG
eQMXnYusyDrlJrLfmhYVmcjFayrEaeFaBacBc6dA
O8AjGsXT0hA6BVruHgvN+Df5IFjX0Mq1fy0TjzM=

That’s a little too long to compare by eye. Would you notice if the 44th character in that string were changed from an i to a j? or the 109th character were changed from the digit 1 to the letter l? Instead what’s compared is a shorter hash code of the actual key. This hash code is called the fingerprint. It looks like 5a:65:0f:5f:21:bb:fd:6a:5a:68:cd:62:58:5d:fb:9f. Those are hexadecimal digits and may sometimes be represented in upper case instead. For instance, 5A:65:0F:5F:21:BB:FD:6A:5A:68:CD:62:58:5D:FB:9F. That difference is not relevant. This still isn’t exactly a legible password, but it’s a little easier to read and verify with only a tiny chance of accidental collision.

Now if you’re connecting to a public server like IBiblio then they may publish their fingerprint somewhere. Make sure you get that fingerprint using https (and not self-signed https either) and you’re good to go. (IBiblio actually gets this wrong. They only publish their keys over unencrypted and vulnerable http.) However in my case I’m connecting to my own system. How do I tell what my system’s fingerprint is so I can compare it?

First thing you have to do is login from the system that you’re verifying. You can’t do the check across the network or the potential man in the middle can still fool you. Once you’re on the system, assuming its a Unix system (including Mac OS X) you ssh to the localhost like so:

~$ ssh localhost
The authenticity of host 'localhost (::1)' can't be established.
RSA key fingerprint is 24:35:bb:55:6c:5f:2a:16:42:d7:b7:ba:9d:7e:d4:f6.
Are you sure you want to continue connecting (yes/no)? 

There’s the local fingerprint. It should match what you saw when you conncted remotely. If it doesn’t, then you’ve got a problem. Alternately you can use ssh-keygen -l -f though you’ll need to know where your system stores its public key. On Linux this is likely /etc/ssh/ssh_host_rsa_key.pub:

$ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub
1024 17:8b:03:34:fc:22:96:70:16:61:ae:53:01:71:a1:70 /etc/ssh/ssh_host_rsa_key.pub

On Mac OS X 10.4 (and possibly other versions) the public key is hiding in /etc/ssh_host_rsa_key.pub instead:

$ ssh-keygen -l -f /etc/ssh_host_rsa_key.pub
1024 17:8b:03:34:fc:22:96:70:16:61:ae:53:01:71:a1:70 /etc/ssh_host_rsa_key.pub

Of course, this only works if the server itself is locally safe; that is, if the attacker is really a man in the middle and not a man on one end or the other. As previously mentioned the FBI tends to attack on one end or the other by installing keylogging hardware to collect passwords rather than by interposing themselves between two systems. However if you’ve already been compromised in that way, then you’ve got bigger problems to deal with; and ssh encryption isn’t going to fix them.

P.S. I still don’t know why my PowerBook’s SSH key changed, but after repeated verification it seems that there’s no man in the middle. My LAN connection seems secure for now.

6 Responses to “Verifying SSH Host Fingerprints”

  1. Emmanuel Says:

    Perhaps did you change from rsa to dsa key ?

  2. Jim Syler Says:

    Okay, here’s the weird thing about this: When you Connect To Server under the File menu in Terminal, it actually uses the -1 flag. So if you don’t use the -1 flag when you “ssh localhost” (in other words, use “ssh -1 localhost”), you get a different hash. Two questions: What does the -1 do? And how do you find the -1 hash using ssh-keygen?

  3. Jim Syler Says:

    To answer my own questions: the -1 option forces use of the RSA1 protocol. And the way to find the hash (besides “ssh -1 localhost” and hoping you’ve never done that and said “yes”) is “ssh-keygen -lf /etc/ssh_host_key.pub” on OS X 10.3 or later (well, only tested on 10.3.9). In other words, get the fingerprint for “etc/ssh_host_key.pub” instead of “etc/ssh_host_rsa_key.pub”.

  4. Daniel Says:

    Thanks. I was wondering exactly the same thing (how do you know it’s who you want it to be) until I finally came across your post. Explanation about fingerprint also very helpful.

  5. Gabe Lager Says:

    Very helpful, indeed. I was wondering how to check the remote host’s fingerprint HASH if you have already accepted it (and thereby added the fingerprint it to your known_hosts file). Jim Syler’s comments answered my question:

    $ ssh-keygen -lf /etc/ssh_host_key.pub

  6. Pierre Says:

    Hi,

    Very clear and usefull post. Beware that a server might have several different keys (one per type of key: DSA, RSA, ECDSA for SSH version 2). Hence, using 2 different SSH clients, you might get 2 different (and valid) fingerprints.

    You might also give a look at http://www.server-stats.net/ssh/ where you can verify all SSH fingerprints, and from how long each key have been seen for the host. (Disclaimer : that’s a website I created and that’s a hobby ๐Ÿ™‚ )