“key values mismatch”: when certificate and key do not belong together

After installing a new certificate the web server refuses to start. The message sounds cryptic, but the cause is almost always one of four things.

What the error looks like

# nginx (OpenSSL 3)
SSL_CTX_use_PrivateKey("/etc/ssl/private/server.key") failed
(SSL: error:05800074:x509 certificate routines::key values mismatch)

# Apache
AH02565: Certificate and private key www.example.com:443:0 from
/etc/ssl/certs/server.crt and /etc/ssl/private/server.key do not match

# HAProxy
inconsistencies between private key and certificate loaded from PEM file

On Windows/IIS the same problem looks different: binding the certificate fails with “A specified logon session does not exist”, or the certificate shows no key icon in the console.

What the server checks

A certificate contains the public key. The server holds the matching private key. On start-up it checks that both form a pair. If they do not, it refuses to serve, because no client could complete a connection.

The four most common causes

1. The certificate belongs to another CSR

The classic: a new CSR with a new key was created for the renewal, but the old key was installed. Or the CSR was created on another server or by a colleague.

2. Wrong order in the certificate file

nginx and HAProxy compare the key with the first certificate in the file. If the intermediate comes first because the files were concatenated in the wrong order, the key cannot match.

# correct: server certificate first, then intermediates
cat server.crt intermediate.crt > fullchain.pem

3. The configuration points to the wrong file

A typo in the path, a symlink to an old file, or certificate and key swapped in the configuration.

4. Windows: certificate without private key

If a .cer file was imported although the CSR was created on another machine, the key is missing. If the CSR was created on the same server, the link to the key can often be restored:

certutil -repairstore my <certificate serial number>

How to find out what belongs together

The quickest way is key match: drop certificate, key and the CSR if you have it into the field. The tool computes the public-key fingerprint of every object and labels what belongs together. It works with RSA and ECC keys, DER files and encrypted keys. Nothing is uploaded.

On the command line it works like this. All three outputs must be identical:

openssl x509 -in server.crt -noout -pubkey | openssl sha256
openssl pkey -in server.key -pubout       | openssl sha256
openssl req  -in server.csr -noout -pubkey | openssl sha256

The often recommended modulus comparison (-modulus) only works for RSA. Comparing the public key also works for ECDSA.

If several keys are lying around, find the matching one like this:

for k in /etc/ssl/private/*.key; do
  echo "$(openssl pkey -in "$k" -pubout 2>/dev/null | openssl sha256 | cut -d' ' -f2)  $k"
done

The fix

FAQ

Can I recover the private key from the certificate?

No. The certificate only contains the public key. If the private key is gone, only a new key with a new CSR and a reissue helps.

Why does the key match the CSR but not the certificate?

Then the certificate was issued for another CSR, for example after several attempts. Check in your CA account which CSR was used, or reissue with the matching CSR.

Is it safe to drop the private key into a web tool?

With key match on hollop.net nothing is transmitted; the computation runs in JavaScript in your browser. If you want to be completely sure, use the OpenSSL commands above.