← back to latest

See which keys can log in to an account without reading base64

ssh-keygen -lf ~/.ssh/authorized_keys

anatomy

ssh-keygen
Most people only ever run it to make a key. The same binary also reads keys, and it understands every public key format OpenSSH writes, so it can summarize a file you would otherwise squint at.
-l
Show the fingerprint instead of generating anything. The fingerprint is a SHA-256 hash of the decoded key blob, base64-encoded with the trailing `=` padding dropped. It is the same string sshd writes to the auth log when that key logs in, which is what makes it useful for matching.
-f
Name the input file. Without it `ssh-keygen` prompts for one interactively. Given a multi-key file like `authorized_keys` or `known_hosts`, it prints one line per key and skips comments, blank lines, and the options such as `from=` or `no-pty` that can sit in front of a key.
~/.ssh/authorized_keys
The list sshd checks when someone tries to log in to this account with a key. Every line in it is a door. Reading it raw gives you several hundred characters of base64 per door; `-l` turns each one into size, fingerprint, comment, and type.

Sample output

256 SHA256:ntaLSnHJ9i9RDaN2l8O/76jgtbhhcs6YwTnMhzhzSJI ada@laptop (ED25519)
3072 SHA256:otA3tNjmlfFG+gAlyt2+YO13UJl5Cz/tJxtFp13A7H4 deploy@ci (RSA)
256 SHA256:wRY+6GdGFlzFrrOrahDlUeUVXrh42/r/K5PvJdEPwQc old key, do not use (ECDSA)

Three keys can log in to this account. The columns are key size in bits, fingerprint, the comment from the end of the line, and the key type. The third one has a comment asking not to be used, which is not the same as being removed. Delete that line from authorized_keys and it stops working on the next login attempt.

When you would reach for it

Someone left the team and you need to know whether their key still opens the production box. A deploy started working from a machine nobody recognizes and you want to match the fingerprint in the auth log to a line in the file. Or you inherited a server and want an inventory of who can get in before you change anything. The raw file answers none of these at a glance; one fingerprint per line does.

Gotchas

  • The comment is whatever the key’s creator typed, or whatever user@hostname was when they ran ssh-keygen. It proves nothing. Match on the fingerprint, which comes from the key itself, and treat the comment as a hint.
  • A line that is not a valid key is skipped without a warning, and the exit status is still 0. A truncated paste disappears from the output, so the file can hold more lines than you see. Compare against grep -c '^[^#]' ~/.ssh/authorized_keys if the count matters. Blank lines and comments are skipped the same way.
  • Pointed at ~/.ssh/known_hosts, the comment column shows the host name, unless the file is hashed. Debian turns on HashKnownHosts in /etc/ssh/ssh_config, so there you get |1|I+XtPGlG... where the name should be. Use ssh-keygen -lF hostname (below) to look up one host instead.
  • Older tools and some cloud consoles still show MD5 fingerprints like aa:be:79:11:.... Those are the same key with a different hash, not a different key. Add -E md5 to compare like with like.
  • On Alpine, ssh-keygen lives in its own openssh-keygen package, separate from the client. macOS 15 and Debian 12 ship it with OpenSSH.

Variants

$ ssh-keygen -lF github.com

Print the fingerprint known_hosts has stored for one host, hashed file or not. Compare it with the fingerprint the provider publishes before you trust it

$ ssh-keyscan -t ed25519 github.com | ssh-keygen -lf -

Fingerprint the key a server presents right now, without connecting. -f - reads from stdin, so the pipe hands over the key without a temp file. ssh-keyscan prints its banner comments to stderr, and they show up above the result

$ ssh-keygen -E md5 -lf ~/.ssh/id_ed25519.pub

Your own key in the old MD5 format, for the dashboards that still display it that way

lineage

ssh-keygen has shipped alongside ssh since Tatu Ylönen's first release in 1995, and it inherited the job of describing keys as well as creating them. For two decades a fingerprint meant an MD5 hash printed as sixteen colon-separated hex pairs. OpenSSH 5.1, in 2008, added the randomart picture you get with `-v`, on the theory that humans compare shapes better than hex strings; the algorithm is usually called the drunken bishop, after the analysis Dirk Loss and colleagues wrote about it. OpenSSH 6.8, in 2015, switched the default to SHA-256 in base64 and added `-E` so you could still ask for the old MD5 form, which is why two tools can show the same key with fingerprints that look nothing alike.