182

Is there an easy way to verify that a given private key matches a given public key? I have a few *.puband a few *.key files, and I need to check which go with which.

Again, these are pub/key files, DSA.

I would really prefer a one-liner of some sort...

Jonathan Southern
  • 1,121
  • 7
  • 22
Loki
  • 6,205
  • 4
  • 24
  • 36

14 Answers14

281

I found a way that seems to work better for me:

ssh-keygen -y -f <private key file>

That command will output the public key for the given private key, so then just compare the output to each *.pub file.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Loki
  • 6,205
  • 4
  • 24
  • 36
  • 2
    what does this exactly do? Why ssh? – sammiwei Feb 15 '12 at 19:16
  • 2
    probably because he's using keypairs for ssh authentication – etarion Apr 25 '12 at 15:06
  • 2
    In my case, a central work server has a few dozen `id_rsa.pub.blahhost` files and I didn't know which one matched the lone `id_rsa` private key & I'm setting up passwordless scp so I can migrate off old websites. Making a new key pair is not an option; I've got my keys set up well and not going to mess that up. – Krista K Dec 30 '13 at 20:43
  • 1
    This solution seems to work for all types of SSH-keys. I even managed to recover a misplaced public key with this approach. – Jari Turkia Jun 13 '18 at 06:37
  • This is brilliant. Thank you – Mamun Apr 02 '21 at 21:37
59

I always compare an MD5 hash of the modulus using these commands:

Certificate: openssl x509 -noout -modulus -in server.crt | openssl md5
Private Key: openssl rsa -noout -modulus -in server.key | openssl md5
CSR: openssl req -noout -modulus -in server.csr | openssl md5

If the hashes match, then those two files go together.

Robert
  • 2,341
  • 18
  • 11
49

For DSA keys, use

 openssl dsa -pubin -in dsa.pub -modulus -noout

to print the public keys, then

 openssl dsa -in dsa.key -modulus -noout

to display the public keys corresponding to a private key, then compare them.

Martin v. Löwis
  • 124,830
  • 17
  • 198
  • 235
20

The check can be made easier with diff:

diff <(ssh-keygen -y -f $private_key_file) $public_key_file

The only odd thing is that diff says nothing if the files are the same, so you'll only be told if the public and private don't match.

mwfearnley
  • 3,303
  • 2
  • 34
  • 35
John D.
  • 1,569
  • 2
  • 13
  • 11
  • 3
    To get output when files match: `diff -s` – Roland Jun 04 '15 at 21:19
  • 4
    This is an excellent answer. (1) `diff -qs` returns a simple "identical/not identical answer. (2) you should delete the comment in the public key file before running the diff. – emory Dec 28 '17 at 13:19
  • Another odd thing is the comment in my `` - I had to resort someone more experienced to know about the anatomy of the public key file. – Salathiel Genese Sep 16 '20 at 19:33
  • The answer was recently updated. `` means you put your key file reference here, such as the name of the private key file path without the brackets and doing whatever escaping you need to if the path has (e.g.) a space in it. It is a placeholder. `$private_key_file` refers to a variable which may or may not be defined and which resolves to the private key file path. If it is not defined, or if the file is otherwise unavailable (e.g. you don't have permissions), this will create an error. – John D. Feb 16 '21 at 02:00
20

Assuming you have the public keys inside X.509 certificates, and assuming they are RSA keys, then for each public key, do

    openssl x509 -in certfile -modulus -noout

For each private key, do

    openssl rsa -in keyfile -modulus -noout

Then match the keys by modulus.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Martin v. Löwis
  • 124,830
  • 17
  • 198
  • 235
7

Enter the following command to check if a private key and public key are a matched set (identical) or not a matched set (differ) in $USER/.ssh directory. The cut command prevents the comment at the end of the line in the public key from being compared, allowing only the key to be compared.

ssh-keygen -y -f ~/.ssh/id_rsa | diff -s - <(cut -d ' ' -f 1,2 ~/.ssh/id_rsa.pub)

Output will look like either one of these lines.

Files - and /dev/fd/63 are identical

Files - and /dev/fd/63 differ

I wrote a shell script that users use to check file permission of their ~/.ssh/files and matched key set. It solves my challenges with user incidents setting up ssh. It may help you. https://github.com/BradleyA/docker-security-infrastructure/tree/master/ssh

Note: My previous answer (in Mar 2018) no longer works with the latest releases of openssh. Previous answer: diff -qs <(ssh-keygen -yf ~/.ssh/id_rsa) <(cut -d ' ' -f 1,2 ~/.ssh/id_rsa.pub)

Bradley Allen
  • 596
  • 5
  • 5
  • 1
    I guess you should elaborate, your post is really close to https://stackoverflow.com/a/22595408/3102264 – mpromonet Mar 04 '18 at 19:04
  • Cross posted to Server Fault: *[How to check if an RSA public / private key pair match](https://serverfault.com/questions/426394/how-to-check-if-an-rsa-public-private-key-pair-match/899929#899929)* – Peter Mortensen Aug 10 '18 at 13:58
5

Delete the public keys and generate new ones from the private keys. Keep them in separate directories, or use a naming convention to keep them straight.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
  • 4
    The question is asking how to verify and the device that we will be verifying it on might not have the facilities to generate a new one. – ArmenB Jul 27 '16 at 22:00
4

If you are in Windows and want use a GUI, with puttygen you can import your private key into it:

enter image description here

Once imported, you can save its public key and compare it to yours.

Zac
  • 4,510
  • 3
  • 36
  • 44
2

The easiest is to compare fingerprints as the public and private keys have the same. Visual comparison is pretty easy by putting the two commands on same line:

ssh-keygen -l -f PRIVATE_KEY; ssh-keygen -l -f PUBLIC_KEY

Programmatically, you'll want to ignore the comment portion so

diff -s <(ssh-keygen -l -f PRIVATE_KEY | cut -d' ' -f2) <(ssh-keygen -l -f PUBLIC_KEY | cut -d' ' -f2)
Oliver
  • 27,510
  • 9
  • 72
  • 103
1

Encrypt something with the public key, and see which private key decrypts it.

This Code Project article by none other than Jeff Atwood implements a simplified wrapper around the .NET cryptography classes. Assuming these keys were created for use with RSA, use the asymmetric class with your public key to encrypt, and the same with your private key to decrypt.

Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
  • I'm looking for something a bit more simple. Say, a shell one liner or the like. I'm on linux, and have the normal stuff such as openssl installed. – Loki Nov 08 '08 at 09:43
  • 3
    That's almost as useful as saying add a public key to your authorized_keys file and use ssh to see which private key works. The method works, but it is a pain. – Bradley Kreider Mar 08 '13 at 21:10
0

If it returns nothing, then they match:

cat $HOME/.ssh/id_rsa.pub >> $HOME/.ssh/authorized_keys
ssh -i $HOME/.ssh/id_rsa localhost
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
RoutesMaps.com
  • 1,628
  • 1
  • 14
  • 19
0

This answer should contain a warning: https://stackoverflow.com/a/67423640/1312559

WARNING! If the public and private key are in the same directory, the fingerprint is calculated for the public key even though the private key is given as a parameter.

-l' Show fingerprint of specified public key file. Private RSA1 keys are also supported. For RSA and DSA keys ssh-keygen tries to find the matching public key file and prints its fingerprint.

Unfortunately I don't have the reputation to comment.

0

A simple script to check matching of the keys with 3 options:

 #!/bin/bash

 PRKEY=mysshkey
 PUKEY=mysshkey.pub

 echo "1. OUTPUT"
 diff <( ssh-keygen -y -e -f "${PRKEY}" ) <( ssh-keygen -y -e -f "${PUKEY}")
 echo -e "\n"

 echo "2. OUTPUT"
 diff <( cut -d' ' -f 2 ${PUKEY} ) <( ssh-keygen -y -f "${PRKEY}" | cut -d' ' -f 2)
 echo -e "\n"

 echo "3. OUTPUT"
 DIFF=$(diff <( cut -d' ' -f 2 ${PUKEY} ) <( ssh-keygen -y -f "${PRKEY}" | cut -d' ' -f 2) )
 if [ "$DIFF" != "" ]; then
  echo "ERROR KEY"
 else
  echo "TRUE KEY"
 fi

If they keys not match you will get an output for output 1 and 2.

If they keys match you get no output.

Output 3 show's a message if keys fit or not.

Z0OM
  • 1
  • 4
  • 18
  • 29
-1

Just use puttygen and load your private key into it. It offers different options, e.g. exporting the corresponding public key.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 1
    this does not allow to test private-public keypair – MatFiz Jul 29 '16 at 12:55
  • Why not? You export the public key from private and compare to the public key file you have. I would prefer the command line, but this method works also. – sekrett Sep 09 '20 at 09:11