Image of the glider from the Game of Life by John Conway
Skip to content

Making Sense of Hashed Hosts in ~/.ssh/known_hosts

I don't expect you to follow this post completely, but it's so amazingly cool, I have to blog it. Consider the hashed sections of ~/.ssh/known_hosts file for (recent) OpenSSH clients, not including the public key parts:

|1|kFJT5z0x3ndyutgZ4E5pRk+ORBA=|hzXvdYUudo+qK9BGlFWtSAUXlXc=
|1|8wo1+FO0hkATPgQZoeNHeIlvAjw=|dt/a9jz9CnLKP72j+Jr8MKMjgEE=
|1|pvBQEKEGLnH0RCJr+8Dmqqnvlrs=|fJJvjyG/TmHFnuIX57nDThq/C4M=
|1|HKV4DzgDkajXoUHf9B82JBu7J10=|c/K+MdJvWaZeJFs/W7iqhqo0wvE=
|1|rtvQhRVnNanQZYkLUMbjoBGNhn0=|0U6a1LUQqLL6P1T2Wji3VWw69pw=
|1|0ziSYi4c+xBXGEBZcNN1LMhYUc4=|qRSN5GSPyQi+fmaVz2zNwkmKoy8=
|1|6nv6Vpk3AYgICHxJGVgVdsYRuq0=|fBNOIz1l3RW+N61jyDPunKX9n7E=
|1|+b4uA+Mq7RHRAFW21qv8aO3rIRs=|1eizMri01IxEKrXquBnwTYP61Ow=
|1|BkB0PZu2qtsLID/Ibe/D68gANQU=|qW6uAzcpecOOKNI4zEvngyfpGkI=
|1|n+QrRn7QXeAJ5hRe2M8v8IspihE=|EqUxXdSeIF1cl1fQjl5zILebkGY=
|1|BOKuKnWojy028tJf9Y671lws0d0=|SuBQJmJZp5JNVYG/rP9yb9ZhJcE=
|1|WACsxtodOiM89kf4rNPLgF1CXZ4=|UTccVeLDZJF3wlH8V05XJNlsOBw=
|1|o6FFoirXYblM7wBMdeJDYGMPI58=|5jJB7T7itY702ZHHByXtSpGk9SE=

The column fields are similar to that of the /etc/shadow file on GNU systems, except where the "$" is the column delimiter, "|" is in this case. If the string was "|1|o6FFoirXYblM7wBMdeJDYGMPI58=|5jJB7T7itY702ZHHByXtSpGk9SE=", then the breakdown is as follows:

  • |1- HASH_MAGIC. This tells the client that the host information has been salted and hashed with the SHA1 algorithm.
  • |o6FFoirXYblM7wBMdeJDYGMPI58= This is the salt applied to the host- base 64 encoded 160-bit string.
  • |5jJB7T7itY702ZHHByXtSpGk9SE= This is the base 64 encoded version of the hashed host

Now, if you want to get at the actual strings, not base 64 encoded, you could run the following command (I admit, not elegant, and could probably be better solved without nesting, and a single awk(1) statement, but I'll get to that later):

% echo $(echo o6FFoirXYblM7wBMdeJDYGMPI58= | openssl base64 -d | xxd | cut -c 10-48) | sed 's/ //g'
a3a145a22ad761b94cef004c75e24360630f239f
% echo $(echo 5jJB7T7itY702ZHHByXtSpGk9SE= | openssl base64 -d | xxd | cut -c 10-48) | sed 's/ //g'
e63241ed3ee2b58ef4d991c70725ed4a91a4f521

There you have it. Very cool. Now, the only question is how to apply the salt to the hostname, to get to the hash? I'm working that out, but I wasn't motivated enough to get to it. Of course, there's no application to this, that I can tell, unless you want to brute force the known_hosts file.

{ 1 } Comments

  1. Jason Yang Xiong using Internet Explorer 8.0 on Windows 7 | January 7, 2014 at 2:01 pm | Permalink

    Regarding how to apply the salt/key to get the hostname hash value, the following is an example.

    This is an entry in ~/.ssh/known_hosts file.
    |1|F1E1KeoE/eEWhi10WpGv4OdiO6Y=|3988QV0VE8wmZL7suNrYQLITLCg= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgwCZx9lGaY+Zhz98TdWqZ01mTzOwRnQO0EIBM8Hx8olxMbrQ1Xa+x/7LBoGyJqeYFunZbFCVpAu+2SBkvf75qV8nTlq3WXnLnprsH5Sq/c9f29ZCcMHevI

    The host name is 192.168.1.61
    The following is how to apply the salt/key to get the hashed host name:
    $hex_key=$(echo $(echo F1E1KeoE/eEWhi10WpGv4OdiO6Y= | base64 -d | xxd -p));echo $(echo -n 192.168.1.61 | openssl sha1 -mac HMAC -macopt hexkey:$hex_key)|awk '{print $2}'|xxd -r -p|base64
    3988QV0VE8wmZL7suNrYQLITLCg=

    So, 3988.....Cg= is the hashed value of 192.168.1.61.

Post a Comment

Your email is never published nor shared.

Switch to our mobile site