About Archive Tags RSS Feed

 

Generating fingerprints from SSH keys

7 October 2015 21:50

I've been allowing users to upload SSH public-keys, and displaying them online in a form. Displaying an SSH public key is a pain, because they're typically long. That means you need to wrap them, or truncate them, or you introduce a horizontal scroll-bar.

So rather than displaying them I figured I'd generate a fingerprint when the key was uploaded and show that instead - This is exactly how github shows your ssh-keys.

Annoyingly there is only one reasonable way to get a fingerprint from a key:

  • Write it to a temporary file.
  • Run "ssh-keygen -lf temporary/file/name".

You can sometimes calculate the key via more direct, but less obvious methods:

awk '{print $2}' ~/.ssh/id_rsa.pub | base64 -d | md5sum

But that won't work for all key-types.

It is interesting to look at the various key-types which are available these days:

mkdir ~/ssh/
cd ~/ssh/
for i in dsa ecdsa ed25519 rsa rsa1 ; do
  ssh-keygen -P "" -t $i -f ${i}-key
done

I've never seen an ed25519 key in the wild. It looks like this:

$ cat ~/ssh/ed25519-key.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMcT04t6UpewqQHWI4gfyBpP/ueSjbcGEze22vdlq0mW skx@shelob

Similarly curve-based keys are short too, but not as short:

ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLTJ5+  \
 rWoq5cNcjXdhzRiEK3Yq6tFSYr4DBsqkRI0ZqJdb+7RxbhJYUOq5jsBlHUzktYhOahEDlc9Lezz3ZUqXg= skx@shelob

Remember what I said about wrapping? Ha!

Anyway for the moment I've hacked up a simple perl module SSH::Key::Fingerprint which will accept a public key and return the fingerprint, as well as validating the key is well-formed and of a known-type. I might make it public in the future, but I think the name is all wrong.

The only code I could easily find to do a similar job is this node.js package, but it doesn't work on all key-types. Shame.

And that concludes this weeks super-happy fun-time TODO-list item.

| 4 comments

 

Comments on this entry

icon Philipp Kern at 10:39 on 7 October 2015

If you use Go, you could use https://godoc.org/golang.org/x/crypto/ssh, marshal the key and hash it with SHA256.

icon Steve Kemp at 10:56 on 7 October 2015
http://www.steve.org.uk/

Thanks for the tip. I sometimes use Go, but this particular project is perl-based.

icon Matthew Walster at 17:14 on 8 October 2015

Why not just pipe it into ssh-keygen instead then?

$ ssh-keygen -l -f /dev/stdin <<<"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFkJ+hQjkgwcK/HVoct871jAi1Z5LsZaAfOOepj9CsJ1 dotwaffle@engelbert" 256 SHA256:NypbzriJTz9K1S7R4XmHRb8cWSH5xu+LLMubZdGHpf8 dotwaffle@engelbert (ED25519)

icon Steve Kemp at 18:08 on 8 October 2015
http://www.steve.org.uk/

My objection wasn't that you needed to write to a file, but that you needed to exec a binary.

But I think that your use of /dev/stdin won't work. Certainly for me it fails:

$ cat ~/.ssh/id_rsa.pub | ssh-keygen -l -f /dev/stdin
/dev/stdin is not a public key file.