42

I have a PEM file which I add to a running ssh-agent:

$ file query.pem
query.pem: PEM RSA private key

$ ssh-add ./query.pem
Identity added: ./query.pem (./query.pem)

$ ssh-add -l | grep query
2048 ef:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX ./query.pem (RSA)

How can I get the key's fingerprint (which I see in ssh-agent) directly from the file? I know ssh-keygen -l -f some_key works for "normal" ssh keys, but not for PEM files.

If I try ssh-keygen on the .pem file, I get:

$ ssh-keygen -l -f ./query.pem                                             
key_read: uudecode PRIVATE KEY----- failed
key_read: uudecode PRIVATE KEY----- failed
./query.pem is not a public key file.

This key starts with:

-----BEGIN RSA PRIVATE KEY-----
MIIEp.... etc.

as opposed to a "regular" private key, which looks like:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,E15F2.... etc.
Unknown
  • 1,341
  • 2
  • 13
  • 19
  • Why would you think that it doesn't work for PEM files? What error do you get when you try it? A `.ssh/id_rsa` file generated by OpenSSH using all the defaults IS a PEM file. The private keys are PEM encoded by default. In fact you can use RSA keys you generate with OpenSSL directly with OpenSSH. – Zoredache Oct 28 '13 at 07:53
  • updated description with output from ssh-keygen on the .pem – Unknown Oct 28 '13 at 07:56
  • (late but necroed) @Zoredache: Before 7.2 (in 2016, after this Q) `ssh-keygen -l` can't read a privatekey file, although other `ssh-keygen` (and `ssh*`) operations do. But when `ssh-keygen` _generates_ a key it writes both the privatekey file e.g. `id_rsa` _and_ a corresponding publickey file with `.pub` added e.g. `id_rsa.pub`. Older `ssh-keygen -l` _will_ try adding `.pub` to the filename you specify and reading that publickey file. – dave_thompson_085 May 18 '19 at 12:03

4 Answers4

61

AWS's "Verifying Your Key-Pair's Fingerprint" provides two one-liners that solves the problem, depending upon how your key was created.

If you created your key pair using AWS:

$ openssl pkcs8 -in query.pem -inform PEM -outform DER -topk8 -nocrypt | openssl sha1 -c
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx

Or, if you created your key pair with a third-party tool:

$ openssl rsa -in query.pem -pubout -outform DER | openssl md5 -c
writing RSA key
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx

(fingerprints redacted in output above)

nosilver4u
  • 13
  • 4
Mike D
  • 837
  • 8
  • 10
47

If you want to retrieve the fingerprint of your lost public key file, you can recover it from the private key file:

$ ssh-keygen -yf path/to/private_key_file > path/to/store/public_key_file

Then you are able to ascertain the public fingerprint:

$ ssh-keygen -lf path/to/store/public_key_file
2048 SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX user@host (RSA)

On some newer systems, this prints the SHA256 fingerprint of the key. You can print the MD5 fingerprint of the key (the colon form) using option -E:

$ ssh-keygen -E md5 -lf path/to/store/public_key_file
2048 MD5:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx user@host (RSA)

Or as one command line:

$ ssh-keygen -yf /etc/ssh/ssh_host_ecdsa_key | ssh-keygen -E md5 -lf -
2048 MD5:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx user@host (RSA)
Ceredig
  • 3
  • 2
ominug
  • 734
  • 7
  • 6
  • @MikeD's answer is actually the "correct" answer for what the OP was looking for (and what I was looking for). AWS provides the fingerprint in the format he showed, with the pairs of digits separated by colons. His solution (taken from the provided AWS page) also generates the fingerprint in this same fashion, so that you can verify correctly. – Mike Williamson Feb 02 '18 at 01:01
7

Here is a one liner that should do what you want without requiring the creation of a public key file locally.

$ ssh-keygen -lf /dev/stdin <<< $( ssh-keygen -f ~/.ssh/keyname.pem -y )
2048 14:df:c7:b7:f1:26:7f:87:d5:e7:10:6c:ac:af:a2:03 /dev/stdin (RSA)

This uses the bash here string <<< in order to have stdin available as a regular file (/dev/stdin) rather than a pipe as ssh-keygen will only operate on a file.

As of Release 7.2 of openssh ssh-keygen supports fingerprinting from standard input:

  • ssh-keygen(1): allow fingerprinting from standard input, e.g. "ssh-keygen -lf -"

Note that this command will break with private keys that use a passphrase and are not using an agent. It should work with pem files generated by AWS or OpenStack which do not use passphrases.

See https://stackoverflow.com/questions/2635360/ssh-keygen-accepting-stdin for more info.

htaccess
  • 446
  • 5
  • 5
  • The release notes didn't say but according to the source as of 7.2 `-l` also supports reading a _privatekey_ file (but _not_ from stdin). – dave_thompson_085 May 18 '19 at 12:10
2

You don't get the fingerprint from the private key file but from the public key file.

In fact, ssh-keygen already told you this:

./query.pem is not a public key file.

Run it against the public half of the key and it should work.

More generally speaking

Think about it: the reason for the fingerprint to exists is that you can identify the public key. In fact, getting a hash of the private key is a potential security issue beside being useless to the server (which doesn't even HAVE the private key in question).

Once you have the public key, the process is to verify that client has a hold on the corresponding private half. Since you already know which keys aou're trying to verify, you don't need the fingerprint.

Stephane
  • 6,432
  • 3
  • 26
  • 47
  • The problem is that I don't have a public key for this private one :( And another thing, `ssh-keygen` works on a RSA private key file that has the extra info at the start (see my initial post), but not on this one.. – Unknown Oct 28 '13 at 08:41
  • Then there is nothing you can do about it. You can't get the public half of the key from the private part any more than you can do the reverse. – Stephane Oct 28 '13 at 09:30
  • 3
    That's incorrect. As @ominug pointed out above, `ssh-keygen -yf` does this. – Steve Bennett Nov 19 '14 at 22:54
  • 4
    @Stephane While correct on a pure RSA level, in practice the way keys are stored in the PKCS spec the format for private keys actually includes both keys. Compare specs for [private](https://tools.ietf.org/html/rfc3447#appendix-A.1.2) vs [public](https://tools.ietf.org/html/rfc3447#appendix-A.1.1) – Håkan Lindqvist Apr 27 '16 at 06:07
  • "You can't get the public half of the key from the private part..." -- oh yes, you probably can. Take the modulus from the private key, and use 65537 as the public exponent, and chances are, you've found the public key. – Jim Flood Jan 08 '18 at 20:20