18

~/.ssh/authorized_keys[2] contains the list of public keys.

Unfortunately, each public key does not specify the key strength ( number of bits ).

Is there a utility that can process this file line by line and output the key strength?

I checked man pages for ssh-keygen, but it looks like it would only work with private keys.

Also, is there a tool that would output sha1 hash the same way as it is displayed in pageant Putty tool?

The format I am looking for:

Key Algorithm  Strength  Hash                                             Comment
ssh-rsa        2048      00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff  user1@host1
ssh-rsa        2048      11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:11  user2@host2
1
  • 4
    Note, that for openssh-7.2, you don't need to do the magic in the accepted answer anymore and you can just feed the ssh-keygen with the whole file. See my answer below.
    – Jakuje
    Aug 28, 2016 at 12:00

5 Answers 5

17

ssh-keygen can do the core of the work (generating a fingerprint from a public key), but it will not automatically process a list of multiple keys as is usually found in an authorized_keys file.

Here is a script that splits up the keys, feeds them to ssh-keygen and produces the table you want:

#!/bin/sh

# usage: authkeys-report <authorized_keys-file>    

set -ue

tmp="$(mktemp -t fingerprint-authkeys.XXXXXXXX)"
trap 'rm -f "$tmp"' 0

while read opts key; do
    case "$opts" in
        [0-9]*|ssh-dss|ssh-rsa)
            # not options, first "word" is part of key
            key="$opts $key"
        ;;
    esac
    echo "$key" >$tmp
    set -- $(ssh-keygen -lf "$tmp")
    bits="$1" fingerprint="$2"

    set -- $key # Note: will mangle whitespace in the comment
    case "$1" in
        [0-9]*) # SSH v1 key
            type=rsa1
            shift 3
        ;;
        ssh-rsa|ssh-dss) # SSH v2 key
            type="$1"
            shift 2
        ;;
        *)
            type=unknown
            set --
        ;;
    esac

    printf '%-14s %-9s %s %s\n' "$type" "$bits" "$fingerprint" "$*"
done <$1
8
  • tmp="$(mktemp -t fingerprint-authkeys)" must be changed to tmp="$(mktemp -t fingerprint-authkeys.XXX)"
    – Stefan
    Sep 16, 2010 at 9:03
  • 1
    @Stefan: Not all versions of mktemp(1) need the Xs: FreeBSD, Mac OS X. But, adding them will not hurt the behavior of those do not need them (they just end up with the Xs before the random suffix). Sep 16, 2010 at 9:49
  • oh.. :) cool... i tried running the script on my arch box... kept saying /home/steve/.scripts/key-strength: line 36: $1: unbound variable
    – Stefan
    Sep 16, 2010 at 9:52
  • Thanks, -l option is really what I was looking for! Still it's unbelievable that you cannot pipe anything to ssh-keygen and MUST have file on disk. Sep 16, 2010 at 11:40
  • 2
    Note, that for openssh-7.2, you don't need to do this magic anymore and you can just feed the ssh-keygen with the whole file. See my answer below.
    – Jakuje
    Aug 28, 2016 at 11:58
13

ssh-keygen in openssh-7.2 (Currently in Fedora and Ubuntu Xenial at least) supports reading multiple keys from a single file. Therefore running simply

# ssh-keygen -l -f ~/.ssh/authorized_keys
2048 SHA256:xh0IVbI... jakuje@jakuje (RSA)
2048 SHA256:xh0IVbI... jakuje@jakuje (RSA)

results in the desired output.

1
  • 2
    Good that they've finally fixed the deficiency. +1 Aug 31, 2016 at 1:49
7

If you have zsh, you can do this as a one-liner:

while read line ; do ssh-keygen -lf =(echo $line); done < .ssh/authorized_keys
4

extrapolating from the zsh solution a bash solution

while read line ; do ssh-keygen -l -f <(echo $line); done < .ssh/authorized_keys 

/dev/fd/63 is not a public key file.
/dev/fd/63 is not a public key file.

almost... This should work, but ssh-keygen seems not to like reading directly from the generated fd. Using a temp file for the <( redirection, it then works. Why?

while read line
do
  cat > /tmp/key <(echo $line)
  ssh-keygen -l -f /tmp/key
done < .ssh/authorized_keys 

1024 1f:c7:da:ef:ff:ff:ff:ff:c8:77:c6:f8:1f:dd:f3:1a /tmp/key (RSA)
3072 83:cd:af:b4:ff:ff:ff:ff:02:30:e7:1e:47:ed:c5:69 /tmp/key (RSA)

of course then you can more easily write this and be happy

while read line
do
  echo $line > /tmp/key
  ssh-keygen -l -f /tmp/key
done < .ssh/authorized_keys 
rm /tmp/key
2
  • Maybe the newer version of ssh-keygen can handle reading from a special file, because your one-liner works perfectly for me. Jan 12, 2016 at 14:18
  • Some versions like reading from stdin, others refuse to. Going through a normal file works everywhere.
    – Marcin
    Oct 25, 2017 at 19:34
3

Script to list all the finger prints from the authorized_keys file, created by saravana:

#!/usr/bin/ksh

USER=`whoami`
USER_H=` lsuser -a home $USER |awk -F '=' '{print $2}'`

cat $USER_H/.ssh/authorized_keys| while read line
do
  echo $line > /tmp/finger_print
  echo "************* Key,finger print details below ***************************"

  cat /tmp/finger_print
  echo

  ssh-keygen -l -f /tmp/finger_print|grep -v not|awk '{print $1" " $2 " " $4}'
  if ssh-keygen -l -f /tmp/finger_print|grep "is not a" > /dev/null 2>&1
  then
    echo "The above key is an Invalid Key,Please correct it"
  fi

  echo "========================================================================"

  rm /tmp/finger_print
done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .