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)?

up vote 140 down vote accepted

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)
  • 4
    do 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 Nov 12 '15 at 21:09
  • 6
    I added a snipped from the OpenSSH Cookbook using sha256sum to the answer. – JonnyJD Nov 13 '15 at 0:33
  • 2
    thank you, you're the only one to give an answer that has actual value. – Florian Heigl Apr 12 '16 at 12:39
  • 1
    Unfortunately I get a different SHA-256 hash when using your awk 1-liner (doesn't match the hash shown by my client) – Jonathan Cross Oct 4 '16 at 21:43
  • 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 Oct 31 '16 at 17:31

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.

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.

  • 2
    all of that is already in the previous answer well formatted. – Jakuje Jan 8 '16 at 16:25

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)

  • 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 Jul 3 '17 at 0:18
  • 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 Jul 3 '17 at 17:36
  • 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 Mar 11 at 19:55

The following command works on Ubuntu 16.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-

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.