How to get all fingerprints for .ssh/authorized_keys(2) file

22,428

Solution 1

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

Solution 2

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 <<<"%"'

Solution 3

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  [email protected] (RSA)
bash $ 

Solution 4

ssh-keygen -l -f - <authorized_keys

produces a nice listing for you:

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

Solution 5

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 -}
Share:
22,428

Related videos on Youtube

childno͡.de
Author by

childno͡.de

geek, information organizer, perfectionist

Updated on September 18, 2022

Comments

  • childno͡.de
    childno͡.de almost 2 years

    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?

    • Admin
      Admin about 2 years
      Please consider updating this question. Your command, ssh-keygen -l -f .ssh/authorized_keys, now seems to fingerprint all keys in the file, at least with my version (OpenSSH_8.4p1). No need for hacky oneliners anymore!
  • childno͡.de
    childno͡.de almost 12 years
    nice @Raphink , thank you. added code.childno.de/marcel/changeset/afdce0dd ;) One note: ssh-keygen -l -f /dev/stdin seems not to work on a mac.. nevertheless not relevant for servers but gnaa apple or is it a BSD "problem" getting /dev/stdin is not a public key file.?!
  • BJladu4
    BJladu4 almost 12 years
    Reading from /dev/stdin is not a great idea in general, it's better to use -, but for some reason ssh-keygen doesn't know about -...
  • Will
    Will almost 10 years
    Doesn't work on Mac?
  • childno͡.de
    childno͡.de almost 10 years
    sorry to say that but that's neither "simplier", nor "smaller" not even "smarter" and doesn't take another approach than listed above. just a script using more error handlers ;)
  • Will
    Will almost 10 years
    Which makes it safer, right? You're welcome to make edits but why downvote? I didn't propose that it was any kind of better solution than yours... I feel a secure tempfile is better, and that more safety is needed for scripting purposes. Also, the version above is noclobber-safe.
  • derekv
    derekv almost 9 years
    For a FreeBSD system (which does not use bash by default), I made the following changes: Assuming bash is installed from ports, change the first line to #!/usr/local/bin/bash. I then called the function by adding this as the last line: fingerprint_keys $@. I saved the script as fingerprints.bash, marking it executable with chmod u+x ./fingerprints.bash. Additionally, I added a comment to the file with the link to this answer, like so, near the top # solution from "Will" on SO http://serverfault.com/a/615892/126742. Call it like so ./fingerprints.bash ~/.ssh/authorized_keys.
  • starfry
    starfry over 7 years
    This does not work if the keys are prefixed with options.
  • 0xC0000022L
    0xC0000022L almost 7 years
    @derekv: the more portable method is to use the following hashbang: #!/usr/bin/env bash, because the path for env is very portable and it tells env to execute the Bash it knows about.
  • 0xC0000022L
    0xC0000022L almost 7 years
    @ℝaphink: I'd go for local file="${1:-$HOME/.ssh/authorized_keys}" to allow for it to work without any arguments and default to the usual ~/.ssh/authorized_keys file and quote the < "$file" used as input to the while loop.
  • Thibaut Barrère
    Thibaut Barrère over 6 years
    This works great, and given it's a one-liner, can easily be used to run the command via SSH. Thanks!
  • thomas
    thomas over 4 years
    does not work with zsh
  • thomas
    thomas over 4 years
    does not work with options field present in authorized_keys
  • thomas
    thomas over 4 years
    this works for me: grep -o 'ssh-.*' ~/.ssh/authorized_keys | xargs -n1 -I% sh -c 'echo "%" | ssh-keygen -l -f /dev/stdin'
  • thomas
    thomas over 4 years
    this works for me with prefixed options: grep -o 'ssh-.*' ~/.ssh/authorized_keys | xargs -n1 -I% sh -c 'echo "%" | ssh-keygen -l -f /dev/stdin'
  • tripleee
    tripleee over 2 years
    The temporary file and all the machinations around it seem useless here; like most modern commands, ssh-keygen -l -f - reads from standard input just fine. Perhaps there was a time when it didn't, but then Bash provides /dev/stdin for those cases.
  • tripleee
    tripleee over 2 years
    /dev/stdin is a Bashism too; it is not guaranteed to work in non-Bash shells. Some OS platforms provide it, but not all.
  • djdomi
    djdomi over 2 years
    that is already shown in the hoghest count answer? did you not read it?
  • Admin
    Admin about 2 years
    Its a little different @djdomi in that is using stdin (the -) arg, which I was able to use like this cat ~/.ssh/authorized_keys | ssh-keygen -lf -.
  • Admin
    Admin about 2 years
    It seems that there's no need to do something different anymore though. While the OP says that command will fingerprint the first key in the file only, I've just run it now and got fingerprints for all of them: wilmer@fiona:~$ ssh-keygen -l -f .ssh/authorized_keys 2048 SHA256:DEtyZ1E+22Gsx9g/k8Wdz2vMk3JyJ9ZgCxytb4aMYSc yubikey-ws-wilmer (RSA) 2048 SHA256:oIePQpcOShOhFlCIXZZv6wUCp96iX7Pg8cdFtTSb8Co yubikey-lap-wilmer (RSA) .....