Determine if private key belongs to certificate?

Information Security Asked by Thanatos on December 25, 2020

Given a certificate¹ and a private key file², how can I determine if the public key on the certificate matches the private key?

My initial thought was to simply encrypt some text with the public key on the cert, and attempt to decrypt it with the private key. If it roundtrips, we’ve got a winner. I just can’t figure out how to do this with OpenSSL.

Alternatively, if I could generate the public key from the private key, I could just compare their fingerprints. SSH seems to have a command for this (ssh-keygen -y -f my_key >, but the hashes don’t match. (I’m nearly certain I have the key corresponding to the cert, as the webserver is serving with it, but I’d like an easier way that spinning up a server to check.)

¹ a .crt file, in x509 format, I think. OpenSSL can read it with openssl x509 -text -in that_cert.crt

² An RSA private key

3 Answers

I'm going to assume you have ssl.crt and ssl.key in your current directory.

If you want to see what's in your certificate it's

# openssl x509 -in ssl.crt -text -noout

Two of the things in here will be the RSA public Key's Modulus and Exponent (in hex).

If you want to see what's in your private key it's

# openssl rsa -in ssl.key -text -noout

Note the public key is usually in there (at the very least the modulus is required to be in there for the private key to work, and the public exponent is usually 65537 or 3). So you can simply check if the modulus and public exponent match. Granted, if you want to check that the private key is actually valid (that is d and e are valid RSA exponents for the modulus m), you would need to run

# openssl rsa -check -in ssl.key -noout

EDIT (2018): Please note if you are checking that a private key coming from an untrusted source corresponds with a certificate, you MUST CHECK that the private key is valid. See here for an example where not checking the validity of a "leaked" private key lead to a CA improperly revoking a certificate. You may skip this step if you know you validly generated the keypair.

Now you can simply generate the public key from both the certificate and the private key and then use diff to check that they don't differ:

# openssl x509 -in ssl.crt -pubkey -noout >
# openssl rsa -in ssl.key -pubout >
# diff

Or as a one liner that doesn't create files (using process substitution):

# diff  <(openssl x509 -in ssl.crt -pubkey -noout) <(openssl rsa -in ssl.key -pubout)

If the keys match, diff shouldn't return anything. (You probably will see "writing RSA key" output to stderr from the second command).

Note your webserver probably would loudly complain if the certificate and private key didn't match. E.g., with nginx using the wrong key (same size, same public exponent, but last year's key) for the certificate nginx is using:

# sudo /etc/init.d/nginx restart
* Restarting nginx nginx                                                                                         
nginx: [emerg] SSL_CTX_use_PrivateKey_file("/etc/nginx/ssl/private/wrong_key.key") failed 
(SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch)
nginx: configuration file /etc/nginx/nginx.conf test failed

Correct answer by dr jimbob on December 25, 2020

OpenSSL can create a test TLS server that will verify that a key and certificate match as it initialises:

openssl s_server -key key.pem -cert cert.pem

If the server starts then the key and certificate match, otherwise the server will fail to start and complain:

error setting private key
140606597580096:error:0B080074:x509 certificate routines:X509_check_private_key:
key values mismatch:../crypto/x509/x509_cmp.c:297:

Acknowledgement goes to dave_thompson_085 for his suggestion in this question's comments.

Answered by Terry Burton on December 25, 2020

The accepted answer is correct, but it only works for RSA keys.

At least since openssl 1.1.1 it is possible to test validity of all types of private keys and here's a one-liner that works for all sorts of keys that openssl supports

 cmp <(openssl x509 -pubkey -in certificate.pem -noout) <(openssl pkey -check -pubout -in private-key.pem -outform PEM)

It will return 'true' if and only if the private key matches the public key in the certificate.

Answered by Manish on December 25, 2020

Add your own answers!

Related Questions

Ask a Question

Get help from others!

© 2023 All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP