166

I have two files, id_rsa and id_rsa.pub. What command can be used to validate if they are a valid pair?

Ryan
  • 6,271

5 Answers5

209

I would prefer the ssh-keygen -y -e -f <private key> way instead of the accepted answer of How do you test a public/private DSA keypair? on Stack Overflow.

ssh-keygen -y -e -f <private key> takes a private key and prints the corresponding public key which can be directly compared to your available public keys. (Hint: beware of comments or key-options.)

(How the hell is it doing that? I can only hope the public key is encoded directly or indirectly in the private key...)

I needed this myself and used the following Bash one-liner. It should output nothing if the keys belong together. Apply a little -q to the diff in scripts and diff only sets the return code appropriately.

PRIVKEY=id_rsa
TESTKEY=id_rsa.pub
diff <( ssh-keygen -y -e -f "$PRIVKEY" ) <( ssh-keygen -y -e -f "$TESTKEY" )
Michuelnik
  • 3,558
83

Depending on where you get the public key file you are testing, the accepted answer may give false positive results. This is because of the behavior described in the comment by @drewbenn. Specifically, when the -e option is used with the private key file as the -f option parameter, it simply parrots (but reformats) what's in the associated public key file.

In other words,

ssh-keygen -y -f id_rsa

(apparently) generates the public key value, and

ssh-keygen -y -e -f id_rsa

simply and outputs (and reformats) the key in the existing id_rsa.pub whatever it is.

In my case, I have to verify that the pair has not been corrupted. So, I decided to compare the following:

ssh-keygen -y -f id_rsa | cut -d' ' -f 2

with

cut -d' ' -f 2 id_rsa.pub

Therefore:

diff <(cut -d' ' -f 2 id_rsa.pub) <(ssh-keygen -y -f id_rsa | cut -d' ' -f 2)

Perhaps this is not as flexible, but it is better for my needs. Maybe it helps someone else.

15

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
  • 260
6

If they're on your local system, stick id_rsa.pub in your $HOME/.ssh/authorized_keys and ssh to localhost using the id_rsa key. If it works, then they match.

cat $HOME/.ssh/id_rsa.pub >> $HOME/.ssh/authorized_keys
ssh -i $HOME/.ssh/id_rsa localhost
Michael Hampton
  • 252,907
2

This is a very old thread, but I found the answers a little bit overengineered. So I just created yet another oneliner :)

[[ `ssh-keygen -yf /path/to/private_key_file` == `cat /path/to/public_key_file` ]] && echo "True" || echo "False"

There might be some edge cases because of the comments but it works fine for me since I never mess with them.

Hope it helps.

P.S.: And yes, please change that accepted answer. False positives might be problematic.

tacan
  • 121