Get SSH server key fingerprint

Is there a way to programmatically obtain a SSH server key fingerprint without authenticating to it?

I’m trying ssh -v [email protected] false 2>&1 | grep "Server host key", but this hangs waiting for a password if key based auth is not setup.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You could do this by combining ssh-keyscan and ssh-keygen:

$ file=$(mktemp)
$ ssh-keyscan host > $file 2> /dev/null
$ ssh-keygen -l -f $file
521 de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef host (ECDSA)
4096 8b:ad:f0:0d:8b:ad:f0:0d:8b:ad:f0:0d:8b:ad:f0:0d host (RSA)
$ rm $file

(unfortunately the much simpler ssh-keyscan host | ssh-keygen -l -f /dev/stdin does not work)

Method 2

I recently had to do this myself so I thought I’d add an answer which shows
how this can be done (with versions of OpenSSH 7.2 or newer) in one line
using process substitution:

ssh-keygen -lf <(ssh-keyscan localhost 2>/dev/null)

(replace localhost with the hostname here)


The following text explains how these commands work and highlights some of the
differences in behaviour between older and newer versions of the OpenSSH
utilities.

Fetch public host keys

The ssh-keyscan command was developed so that users can obtain public host
keys without needing to authenticate to the SSH server. From its man page:

ssh-keyscan is a utility for gathering the public ssh host keys of a
number of hosts. It was designed to aid in building and verifying
ssh_known_hosts files.

Key type

The type of key to be fetched is specified using the -t option.

  • rsa1 (obsolete SSH Protocol version 1)
  • rsa
  • dsa
  • ecdsa (recent versions of OpenSSH)
  • ed25519 (recent versions of OpenSSH)

In modern OpenSSH releases, the default key types to be fetched are rsa
(since version 5.1), ecdsa (since version 6.0), and ed25519 (since version
6.7).

With older versions of ssh-keyscan (before OpenSSH version 5.1), the
default key type was the out-dated rsa1 (SSH Protocol 1) so the key types
would need to be explicitly specified:

ssh-keyscan -t rsa,dsa hostname

Get fingerprint hashes of Base64 keys

ssh-keyscan prints the host key of the SSH server in Base64-encoded
format. To convert this to a fingerprint hash, the ssh-keygen utility can be
used with its -l option to print the fingerprint of the specified public
key.

If using Bash, Zsh (or the Korn shell), process
substitution
can be used
for a handy one-liner:

ssh-keygen -lf <(ssh-keyscan hostname 2>/dev/null)

Note: With versions of OpenSSH before 7.2, the functions used by
ssh-keygen to read files, did not handle named pipes (FIFOs) very well so
this method wouldn’t work, thus requiring the use of temporary files.

Hashing algorithms

Recent versions of ssh-keygen print SHA256 fingerprint hashes of the keys.
To get MD5 hashes of the server key fingerprints (the old behaviour), the -E
option can be used to specify the hash algorithm:

ssh-keygen -E md5 -lf <(ssh-keyscan hostname 2>/dev/null)

Using a pipeline

If using a POSIX shell (such as dash) which doesn’t feature process substitution,
the other solutions using temporary files will work. However, with newer versions
of OpenSSH (since 7.2), a simple pipeline can be used since ssh-keygen will
accept - as a filename for the standard input stream, allowing a one-line
pipeline command.

ssh-keyscan hostname 2>/dev/null | ssh-keygen -E md5 -lf -

Method 3

nmap provides this ability by using the ssh-hostkey script.

To return the key’s hexadecimal fingerprint:

$ nmap [SERVER] --script ssh-hostkey

To return the key’s content:

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey=full

To return the key’s visual bubble

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey='visual bubble'

To return all of the above:

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey=all

Source: nmap docs

Method 4

filezilla displays keys hashed with md5 in hexadecimal format.

to find this on your ubuntu linux machine use this command:

ssh-keygen -l -E md5 -f <(ssh-keyscan localhost 2>/dev/null)

note: replace “localhost” with the ip of the machine you wish to check.

Method 5

The simple answer when you already have access to the server is:

ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub

Now, you might not be using the RSA key: if when connecting, ssh tells you

ECDSA key fingerprint is SHA256: XXXXX

You need to use /etc/ssh/ssh_host_ecdsa_key.pub instead. (notice _ecdsa_).
A more universal command that lists all keys can thus be constructed (source):

for f in /etc/ssh/ssh_host_*_key.pub; do ssh-keygen -lf "$f"; done

You could write down the list when setting the server up, for future reference. Another option is to store them in DNS records (Archive):

  1. Add the following DNS record: <hostname> IN SSHFP <key-type> <hash-type> <fingerprint> (ssh-keygen can print this line for you if you give it the hostname: ssh-keygen -r hostname -f /etc/ssh/ssh_host_ecdsa_key.pub)
  2. Connect with ssh -o VerifyHostKeyDNS=yes [email protected] or enable it by default by adding VerifyHostKeyDNS=yes to the client config.

From the ssh-keygen (1) manpage:

-l Show fingerprint of specified public key file. For RSA and DSA keys ssh-keygen tries to find the matching public key file and prints its fingerprint. If combined with -v, a visual ASCII art representation of the key is supplied with the fingerprint.

-f filename
Specifies the filename of the key file.

-r hostname
Print the SSHFP fingerprint resource record named hostname for the specified public key file.

Method 6

Here is a shell script (mainly Bourne shell but using local keyword, which is available in most modern /bin/sh) I’ve written to do this. Use it like ssh-hostkey hostname. It will show both the sha256 and md5 format fingerprints for all hostkeys for the given hostname or IP address. You can also manually specify “md5” or “sha256” as the second argument to only show that particular format.

It uses a temporary file instead of piping to make it compatible with older OpenSSH packages (as described in other answers). The temporary file uses /dev/shm (shared memory) if available.

#!/bin/sh
usage () {
  printf '%sn' "Usage: ssh-hostkey HOSTNAME [FPRINTHASH]"
}

ssh_hostkey () {
  local host="$1"
  local fprinthash="$2"
  local tmp=

  case "$host" in
    -h|--help|'')
      usage >&2
      return 1
      ;;
  esac

  case "$fprinthash" in
    md5|sha256|'') true;;
    *)
      usage >&2
      printf '%sn' "Fingerprint hash may be 'md5' or 'sha256'" >&2
      return 2
      ;;
  esac

  if test -d /dev/shm
  then tmp="$(mktemp -d -p /dev/shm)"
  else tmp="$(mktemp -d)"
  fi

  trap 'trap - INT TERM EXIT; rm -rf "$tmp"' INT TERM EXIT
  ssh-keyscan "$host" > "$tmp/f" 2> /dev/null
  case "$fprinthash" in
    sha256|'') ssh-keygen -l -f "$tmp/f" 2> /dev/null;;
  esac
  case "$fprinthash" in
    md5|'') ssh-keygen -l -E md5 -f "$tmp/f" 2> /dev/null;;
  esac

  trap - INT TERM EXIT
  rm -rf "$tmp" > /dev/null 2>&1
}

ssh_hostkey "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="af8bef">[email protected]</a>"

Method 7

For my own server I use this:

ssh-keygen -l -E md5 -f <(cat /etc/ssh/ssh_host_*_key.pub)
ssh-keygen -l -E sha256 -f <(cat /etc/ssh/ssh_host_*_key.pub)


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x