55

Is there a simple way to get a list of all fingerprints entered in the .ssh/authorized_keys || .ssh/authorized_keys2 file?

ssh-keygen -l -f .ssh/authorized_keys 

will only return fingerprint of first line / entry / publickey

hack with awk:

awk 'BEGIN { 
    while (getline < ".ssh/authorized_keys") {
        if ($1!~"ssh-(r|d)sa") {continue}
        print "Fingerprint for "$3
        system("echo " "\""$0"\"> /tmp/authorizedPublicKey.scan; \
            ssh-keygen -l -f /tmp/authorizedPublicKey.scan; \
            rm /tmp/authorizedPublicKey.scan"
        )
    }
}'

but is there an easier way or ssh command I didn't find?

Will
  • 1,157

7 Answers7

62

Here's another hack using plain bash without temporary files:

while read l; do
  [[ -n $l && ${l###} = $l ]] && ssh-keygen -l -f /dev/stdin <<<$l;
done < .ssh/authorized_keys

You can easily make it a function in your .bashrc:

function fingerprints() {
  local file="${1:-$HOME/.ssh/authorized_keys}"
  while read l; do
    [[ -n $l && ${l###} = $l ]] && ssh-keygen -l -f /dev/stdin <<<$l
  done < "${file}"
}

and call it with:

$ fingerprints .ssh/authorized_keys
raphink
  • 13,027
12

A one-liner based on the /dev/stdin trick from ℝaphink's answer and man xargs → EXAMPLES:

egrep '^[^#]' ~/.ssh/authorized_keys | xargs -n1 -I% bash -c 'ssh-keygen -l -f /dev/stdin <<<"%"'
Law29
  • 3,617
  • 1
  • 18
  • 30
akavel
  • 377
8

Here's a portable way to show all key fingerprints for a given file, tested on Mac and Linux:

#!/bin/bash

fingerprint_keys()
{
    if (( $# != 1 )); then
        echo "Usage: ${FUNCNAME} <authorized keys file>" >&2
        return 1
    fi

    local file="$1"
    if [ ! -r "$file" ]; then
        echo "${FUNCNAME}: File '${file}' does not exist or isn't readable." >&2
        return 1
    fi

    # Must be declared /before/ assignment, because of bash weirdness, in
    # order to get exit code in $?.
    local TMPFILE

    TEMPFILE=$(mktemp -q -t "$0.XXXXXXXXXX")
    if (( $? != 0 )); then
        echo "${FUNCNAME}: Can't create temporary file." >&2
        return 1
    fi

    while read line; do
        # Make sure lone isn't a comment or blank.
        if [[ -n "$line" ]] && [ "${line###}" == "$line" ]; then
            # Insert key into temporary file (ignoring noclobber).
            echo "$line" >| "$TEMPFILE"

            # Fingerprint time.
            ssh-keygen -l -f "$TEMPFILE"

            # OVerwrite the file ASAP (ignoring noclobber) to not leave keys
            # sitting in temp files.
            >| "$TEMPFILE"
        fi
    done < "$file"

    rm -f "$TEMPFILE"
    if (( $? != 0 )); then
        echo "${FUNCNAME}: Failed to remove temporary file." >&2
        return 1
    fi
}

Example Usage:

bash $ fingerprint_keys ~/.ssh/authorized_keys
2048 xx:xx:xx:xx:xx:xx:xx:xx:bb:xx:xx:xx:xx:xx:xx:xx  x@x.local (RSA)
bash $ 
Will
  • 1,157
5

Since recent versions of OpenSSH, this command already produces a nice listing for you:

ssh-keygen -l -f authorized_keys

Example:

# ssh-keygen -l -f authorized_keys
2048 SHA256:GzZ7.................................RqTEag foo (RSA)
2048 SHA256:/y0.......................................4 bar (RSA)
2048 SHA256:p.........................................k bleech (RSA)

So consider just upgrading your OpenSSH client.

Jon Bundesen
  • 61
  • 1
  • 1
1

And should anyone need to do it on Windows / in PowerShell:

gc authorized_keys | foreach {$_ |ssh-keygen -l -f -}

or the fully-blown version without aliases looking for your user profile directory:

(Get-Content ((Get-Content env:/userprofile)+"/.ssh/authorized_keys")) | foreach {$_ |ssh-keygen -l -f -}
0

If and when reading from /dev/stdin it's an issue you may want to use process redirection without temporary files:

while read -r l; do
  [[ -n "$l" && ${l###} = "$l" ]] && ssh-keygen -l -f <(echo "$l");
done < .ssh/authorized_keys
tripleee
  • 1,504
emaV
  • 101
0

This is a version of ℝaphink's answer that will work on all sh-compatible shells.

fingerprints() {
    _fingerprints_file="${1:-$HOME/.ssh/authorized_keys}"
    while read -r l; do
        [ -n "$l" ] && [ "${l###}" = "$l" ] && printf '%s\n' "$l" | ssh-keygen -l -f /dev/stdin
    done < "${_fingerprints_file}"
    unset _fingerprints_file
}