SHA256 ssh fingerprint given by the client but only md5 fingerprint known for server

119

51

When connecting to a new/unknown server (with recent OpenSSH), for example:

ssh example.com

You get the fingerprint like below:

The authenticity of host 'example.org (192.0.2.42)' can't be established.
RSA key fingerprint is SHA256:7KMZvJiITZ+HbOyqjNPV5AeC5As2GSZES5baxy1NIe4.
Are you sure you want to continue connecting (yes/no)?

However, fingerprints are usually given for the server in this form:

f6:fc:1c:03:17:5f:67:4f:1f:0b:50:5a:9f:f9:30:e5

How can I check the authenticity (without bugging the server admins to provide an SHA256 fingerprint)?

JonnyJD

Posted 2015-06-18T14:18:11.363

Reputation: 3 203

Related post get SSH key fingerprint in (old) hex format on new version of openssh.

– JamesThomasMoon1979 – 2018-12-17T05:42:58.573

Answers

153

Previously the fingerprint was given as a hexed md5 hash. Starting with OpenSSH 6.8 the fingerprint is now displayed as base64 SHA256 (by default). You can't compare these directly.

They also added a new configuration option FingerprintHash. You can put

FingerprintHash md5

in your ~/.ssh/config to revert to the old (less secure) default or just use this option for single use:

ssh -o FingerprintHash=md5 example.org

which would give the fingerprint as

MD5:f6:fc:1c:03:17:5f:67:4f:1f:0b:50:5a:9f:f9:30:e5

Hopefully server admins provide both types of fingerprints in the near future.

EDIT:

As given in the Arch Linux forums, there is also a third option:

Host example.org
    FingerprintHash md5

EDIT:

You can generate the hash of an arbitrary key as given on the OpenSSH Cookbook:

Retrieve the key:

  • download the key with ssh-keyscan example.org > key.pub
  • or: find the keys on the server in /etc/ssh

Generate the hash:

  • make sure you have only one line/type, so either delete all others in key.pub or run ssh-keyscan -t rsa example.org > key.pub
  • ssh-keygen -l -f key.pub (default hash, depending on OpenSSH version)
  • ssh-keygen -l -f key.pub -E md5 (md5 on current OpenSSH)
  • awk '{print $2}' ssh_host_rsa_key.pub | base64 -d | sha256sum -b | awk '{print $1}' | xxd -r -p | base64 (sha256 on old OpenSSH)
  • (You might need to start the line with awk '{print $3}' for newer versions of ssh-keyscan because the format changed)

JonnyJD

Posted 2015-06-18T14:18:11.363

Reputation: 3 203

4do you happen to know how I can get the sha256 fingerprint on the server in case I have access there? ssh-keygen -lf on the server only gives me the md5 print, and for the life of me I can't find how to get the sha256 one either in the man pages or the www so far... – codeling – 2015-11-12T21:09:37.217

6I added a snipped from the OpenSSH Cookbook using sha256sum to the answer. – JonnyJD – 2015-11-13T00:33:13.747

2thank you, you're the only one to give an answer that has actual value. – Florian Heigl – 2016-04-12T12:39:07.183

1Unfortunately I get a different SHA-256 hash when using your awk 1-liner (doesn't match the hash shown by my client) – Jonathan Cross – 2016-10-04T21:43:19.613

Thanks for the note, there were two potential problems: 1) some hosts have multiple keys, the awk line only works with one 2) recent versions of ssh-keyscan use a different format, so one has to use $3 instead of $2. (both fixed with an edit) – JonnyJD – 2016-10-31T17:31:38.023

Use the -t option on ssh-keyscan to request other key types, such as the preferable ed25519: ssh-keyscan -t ed25519 example.org > key.pub – Ashley – 2016-11-01T01:07:44.767

2sha256sum -b | awk '{print $1}' | xxd -r -p can be replaced by openssl sha256 -binary not requiring vim installed. Resulting commandline would be: awk '{print $2}' ~/.ssh/id_rsa.pub | base64 -d | openssl sha256 -binary | base64 – Alexander Tumin – 2019-05-28T13:29:06.277

1@JonathanCross Note that base64 utility would produce padded output (i.e. possibly ending with one or two equals signs), while openssh client does not pad base64 in it's log. – Alexander Tumin – 2019-05-28T13:31:11.767

27

Just created small bash script which will print table with fingerprints for all key ciphers allowed on server (according to /etc/ssh/sshd_config) in both SSH-256 and MD5 algo. Here is an example output:

 +---------+---------+-----------------------------------------------------+
 | Cipher  | Algo    | Fingerprint                                         |
 +---------+---------+-----------------------------------------------------+
 | RSA     | MD5     | MD5:15:66:80:fd:79:d8:c0:92:e8:39:4a:bc:4e:c4:00:15 |
 | RSA     | SHA-256 | SHA256:G+rKuLGk+8Z1oxUV3cox0baNsH0qGQWm/saWPr4qZMM  |
 +---------+---------+-----------------------------------------------------+
 | ECDSA   | MD5     | MD5:f5:90:5c:03:2e:38:1b:c9:86:bd:86:47:5d:22:79:17 |
 | ECDSA   | SHA-256 | SHA256:GGmuOzsG4EGeRV9KD1WK7tRf3nIc40k/5jRgbTZDpTo  |
 +---------+---------+-----------------------------------------------------+
 | ED25519 | MD5     | MD5:d1:5a:04:56:37:f4:75:19:22:e6:e5:d7:41:fd:79:fa |
 | ED25519 | SHA-256 | SHA256:QVdqYeVzvsP4n5yjuN3D2fu8hDhskOxQCQAV5f9QK7w  |
 +---------+---------+-----------------------------------------------------+

 +---[RSA 2048]----+ +---[RSA 2048]----+ +---[ECDSA 256]---+ +---[ECDSA 256]---+ +--[ED25519 256]--+ +--[ED25519 256]--+
 |.oE.   +.++      | |        .o+=     | |      ... Eoo    | |  .. o.o..      .| |        ooo++o.+*| |   .o++o. +oo    |
 |  .   o +oo.     | |        .o= =    | |     +.=.=.o .   | | . .o *..      ..| |       . oo.+o.o=| |      ...o.+     |
 |   + . . o.=     | |       ... X +   | |    . X.o.*      | |o o  ++o      .. | |        . o. ...+| |       ..oo.o .  |
 |    = +  .+ o    | |      ..  = + o  | |     + = o o     | |.+  .o.o     .o  | |         +    ..o| |        =oo .+   |
 |   o o .S  .     | |     . .S  o o   | |    . = S   .    | |...  oo.S  .E* * | |        S      ..| |       .SO .  .  |
 |    +            | |    . E. =o..    | |     o           | | .. o.  . o *.O o| |              .  | |        o B .o.. |
 |   o             | | .o. *.o. *.     | |                 | |   ...   . o * * | |               . | |         E *..=.o|
 |    .            | | oo=...  +.      | |                 | |    +.      o + o| |                E| |          . +.+B+|
 |                 | |o+=.o....o+o     | |                 | |   .o+         . | |                 | |           o.ooOX|
 +------[MD5]------+ +----[SHA256]-----+ +------[MD5]------+ +----[SHA256]-----+ +------[MD5]------+ +----[SHA256]-----+

Script will run also on servers with SSH version below 6.8 (before -E md5 option was added).

Edit: Updated versions for even more recent versions of SSH which switched default ciphers now with ASCII images support.

#!/bin/bash
# server_ssh_fingerprints
#
# Version 0.2
#
# 2016 Kepi <kepi@igloonet.cz
# MIT License
#
# Print fingerprint matrix for all allowed Host Keys
# with all allowed ciphers and MD5 and SHA-256 algos
#
# Changelog:
#
# 2018-03-11 (0.2):
# - Support for newer versions of OpenSSH
# - Added visual keys for all algos too - only in recent OpenSSH versions

# standard sshd config path
SSHD_CONFIG=/etc/ssh/sshd_config

# helper functions
function tablize {
    awk '{printf(" | %-7s | %-7s | %-51s |\n", $1, $2, $3)}'
}
LINE=" +---------+---------+-----------------------------------------------------+"

# header
echo "$LINE"
echo "Cipher" "Algo" "Fingerprint" | tablize
echo "$LINE"

declare -A ALGOS
declare -a ASCII

# fingerprints
while read -r host_key; do
    cipher=$(echo "$host_key" | sed -r 's/^.*ssh_host_([^_]+)_key\.pub$/\1/'| tr 'a-z' 'A-Z')
    if [[ -f "$host_key" ]]; then
        if ssh-keygen -E md5 -l -f "$host_key" &>/dev/null; then
        IFS=$'\n'

        for algo in md5 sha256; do
            n=0
            for line in $(ssh-keygen -E $algo -lv -f "$host_key"); do
                n=$(( n + 1))
                if [[ $n -eq 1 ]]; then
                    ALGOS[$algo]=$(echo "$line" | awk '{print $2}')
                else
                    ASCII[$n]="${ASCII[$n]} ${line}"
                fi
            done
        done
        else
            ALGOS[md5]=$(ssh-keygen -l -f "$host_key" | awk '{print $2}')
            ALGOS[sha256]=$(awk '{print $2}' "$host_key" | base64 -d | sha256sum -b | awk '{print $1}' | xxd -r -p | base64)
        fi

        echo "$cipher" MD5 "${ALGOS[md5]}" | tablize
        echo "$cipher" SHA-256 "${ALGOS[sha256]}" | tablize
        echo "$LINE"
    fi
 done < <(awk '/^HostKey/ {sub(/^HostKey\s+/,"");print $0".pub"};' $SSHD_CONFIG)

echo
for line in "${ASCII[@]}"; do
    echo "$line"
done

This is just pretty print using information from JonnyJD's answer. Thanks.

Kepi

Posted 2015-06-18T14:18:11.363

Reputation: 396

2

I made it more robust and improved functionality slightly; version 0.3 (with changelog) here: https://github.com/unixnut/scripts/blob/master/ssh_fprint Thanks for writing this, it is awesome!

– Alastair Irvine – 2018-04-29T14:57:51.383

6

it turns out ssh-keygen (sometime after version 6.6; presumably 6.8) has a -E md5 option which will cause it to print out the fingerprint as an md5 fingerprint. So, if you can independently grab the public key file of the server, you can feed it to ssh-keygen -E md5 -l -f ssh_host_rsa_key.pub and get your familiar fingerprint.

Greg Minshall

Posted 2015-06-18T14:18:11.363

Reputation: 169

2all of that is already in the previous answer well formatted. – Jakuje – 2016-01-08T16:25:50.993

3

The following one-liner works (at least) on Ubuntu 16.04,18.04 / Centos >= 7

(Tested with servers: openssh 3.9 - openssh 7.4)

ssh-keygen -l -E md5 -f <(ssh-keyscan -t rsa 192.168.2.1) \
| awk '{print $2}' | cut -d":" -f 2-

Output:

# 192.168.2.1:22 SSH-2.0-OpenSSH_5.3
65:2c:c4:03:03:2f:6d:c0:c0:09:79:e7:33:c4:f1:78

Marinos An

Posted 2015-06-18T14:18:11.363

Reputation: 360

1

tried to modify to get also random art into table:

# standard sshd config path
SSHD_CONFIG=/etc/ssh/sshd_config

# helper functions
function tablize {
        awk '{printf("| %-7s | %-51s |\n", $1, $3)}'
}
LINE="+---------+-----------------------------------------------------+"

# header
echo $LINE
echo "Cipher" "Fingerprint" "Fingerprint" | tablize
echo $LINE

# fingerprints
for host_key in $(awk '/^HostKey/ {sub(/^HostKey\s+/,"");print $0".pub"};' $SSHD_CONFIG); do
        cipher=$(echo $host_key | sed -r 's/^.*ssh_host_([^_]+)_key\.pub$/\1/'| tr '[a-z]' '[A-Z]')
        if [[ -f "$host_key" ]]; then
                md5=$(ssh-keygen -l -f $host_key -E md5 | awk '{print $2}')
                sha256=$(ssh-keygen -l -f $host_key | awk '{print $2}')
                art_sha256=$(ssh-keygen -lv -f $host_key | grep -v -w "256 SHA256" | grep -v -w "1024 SHA256" | grep -v -w "2048 SHA256")
                art_md5=$(ssh-keygen -lv -f $host_key -E md5 | grep -v "256 MD5" | grep -v "1024 MD5" | grep -v "2048 MD5")

                echo $cipher MD5 $md5 | tablize
                echo $cipher SHA-256 $sha256 | tablize
                echo $art_sha256 | tablize
                echo $art_md5 | tablize
                echo $LINE
        fi
done

... but I'm not a programmer actually and the script does not work as expected. Would appreciate if anyone can help to fix (also cleanup). There would be nice to have sha256 and md5 random art images side by side to use space more efficiently. I modified also md5 and sha256 commands as the original ones did not work for me (probably too new system) - only sha256 appreared into table with "=" sign in the end which was not part of actual fingerprint and could not remove it.

(sorry I could not comment as I registered recently)

zeroconf

Posted 2015-06-18T14:18:11.363

Reputation: 21

If you have a new question, please ask it by clicking the Ask Question button. Include a link to this question if it helps provide context.

– Donald Duck – 2017-07-03T00:18:15.880

Well - as you see - it is a not new question but actually admitting that proposed script did not work as expected and a new and still not yet complete version has been proposed. I could modify existing script so it works as expected but I tried to add the random art and this part id not complete.

Actually there is one proposal how to compare certain public key and offered key but this variant is not MITM-proof:

ssh-keyscan -t ecdsa xxx.xxx.xxx.xxx | ssh-keygen -lv -f - && ssh -X -o VisualHostKey=yes -i ~/.ssh/key user@xxx.xxx.xxx.xxx – zeroconf – 2017-07-03T17:36:22.467

I didn't see your comments but today got same idea, so my answer is now updated with working version for more recent OpenSSH versions, ASCII art included. – Kepi – 2018-03-11T19:55:24.940