KeyPairMismatchException: private and public keys don't match when uploading to AWS Load Balancer

After updating my SSL certificates this morning as I normally do, everything looked ok, but when I try to upload them into the AWS Load Balancer using the web console, I get the following error:

Failed to import to IAM
KeyPairMismatchException: The private key did not match the public key provided. Please verify the key material and try again.

I'm assuming the error is saying the uploaded key files don't match somehow, so I checked several things:

  • Verify that the files are in PEM format: yes, the blocks in the .key file begin with "-----BEGIN PRIVATE KEY-----" and end with "-----END PRIVATE KEY-----", and the blocks in the .crt and chain files begin with "-----BEGIN CERTIFICATE-----" and end with "-----END PRIVATE KEY-----".
  • Verify that the key files match: yes, I ran "openssl x509 -noout -modulus" on both the .key file and the .crt file and the md5 outputs matched.
  • Verify that the public keys contained in the .key and .crt files are the same: yes, I ran "openssl x509 -in zoomroses.com.crt -noout -pubkey" and "openssl rsa -in zoomroses.com.key -pubout" and the outputs matched.
  • Verify that the dates of the certificate are correct: yes, I ran "openssl verify -CAfile zoomroses.com.crt" and got "notBefore=Mar 27 11:25:36 2025 GMT, notAfter=Jun 25 11:25:35 2025 GMT". The current time was a bit after 12:00:00 2025 GMT.
  • Verify the validity of the chain file: yes, I ran "openssl verify -partial_chain -CAfile chain.crt zoomroses.com.crt" and the output was "zoomroses.com.crt: OK".

What am I missing?

My domain is:

zoomroses.com

I ran this command:

getssl -u -a

It produced this output:

Renewing SSL certificates.
Check all certificates
Registering account
Verify each domain
Verifying zoomroses.com
copying challenge token to /home/www/html/.well-known/acme-challenge/uVvQWx5EukFjcfjOIVGLOky9fYeB5oRIeW9vBzA7NXI
sending request to ACME server saying we're ready for challenge
checking if challenge is complete
Pending
checking if challenge is complete
Verified zoomroses.com
Verifying www.zoomroses.com
copying challenge token to /home/www/html/.well-known/acme-challenge/FBfejldSIUHoddBOuSC7mMxIjWR-RNqVWbdWeIpN4_Q
sending request to ACME server saying we're ready for challenge
checking if challenge is complete
Pending
checking if challenge is complete
Verified www.zoomroses.com
Verification completed, obtaining certificate.
Requesting Finalize Link
Requesting Order Link
Requesting certificate
Certificate saved in /root/.getssl/zoomroses.com/zoomroses.com.crt
purge /root/.getssl/zoomroses.com/archive/2024_10_14_09_42
purge /root/.getssl/zoomroses.com/archive/2024_10_14_10_20
copying domain certificate to /home/www/ssl/zoomroses.com/zoomroses.com.crt
copying private key to /home/www/ssl/zoomroses.com/zoomroses.com.key
copying CA certificate to /home/www/ssl/zoomroses.com/chain.crt
reloading SSL services
/root/.getssl/zoomroses.com/zoomroses.com.crt didn't match server
getssl: zoomroses.com - rsa certificate obtained but certificate on server is different from the new certificate

My web server is (include version)

Apache/2.4.62

The operating system my web server runs on is (include version):

Amazon Linux 2023.6.20241111

My hosting provider, if applicable, is:

Amazon Web Services

I can login to a root shell on my machine (yes or no, or I don't know):

Yes

I'm using a control panel to manage my site (no, or provide the name and version of the control panel):

No (Amazon Web Services Web Console)

The version of my client is (e.g. output of certbot --version or certbot-auto --version if you're using Certbot):

getssl version 2.49

Have you tried re-uploading the existing cert/key pairing (or a previous one), to test if AWS has a bug/regression?

3 Likes

I'd also suggest carefully retrying your upload. I see you got two certs for that domain recently so make sure you are using the matched pair of cert files.

But, you have an AWS Load Balancer and AWS Route53. Why not use an AWS ACM certificate in your Load Balancer instead of the LE cert?

6 Likes

Thanks for the replies. I have it working now, and I know what caused the problem. Me. This was entirely pilot error. I'll explain my stupidity in case it helps someone else.

When I upload the certificate files to the load balancer, I copy and paste them from a terminal window I have open on one of the instances where the files were renewed. Instead of typing "cat mydomain.com.crt", for some reason, after doing this same thing a thousand times before, I typed "cat *.crt". Which, of course, included both "mydomain.com.crt" and "chain.crt". Hence, two certificate files that I dutifully copied and pasted into the ELB as the body of the certificate. No wonder it complained that it didn't match the private key.

MikeMcQ: thanks for the suggestion about using ACM instead of IAM. I've been doing it this way so long that I didn't realize there might be an easier method. One thing I'm not clear about though... if I let ACM renew the certificate for the ELB (the bare domain), do I still have to renew the certificate on each individual EC2 instance in the ELB? (live1.mydomain.com, live2.mydomain.com, etc.) Or can ACM renew those somehow as well, and then each instance could somehow download their own certificate files?

Thanks!
Russell

2 Likes

Yes, if you want HTTPS between the ELB and your EC2s you still need certs on EC2. The AWS ACM certs are only for selected AWS services and there is not a way to get the private key for those certs. That's why you can't use ACM certs in EC2.

The ACM certs on ELB would just avoid the import step. Similar concept as when using AWS CloudFront. You have AWS ACM Certs for the CF edge for the HTTPS between the user-agent and it. And, then your own cert for HTTPS between the CF edge and your origin server.

2 Likes

Thanks! I need a certificate for each instance individually (live1.mydomain.com) so I can connect to it directly in a browser via SSL, as well as for the bare domain in the ELB (mydomain.com). So right now, I have each instance using getssl to renew Let's Encrypt certificates for themselves (live1.mydomain.com) and the bare domain (mydomain.com). Then I import the certificate files for mydomain.com from one of the instances to the ELB.

It sounds like if I use ACM, I could let it completely handle the renewal of mydomain.com and www.mydomain.com, and stop renewing them on the instances. But I'd still need to renew each instance's own domain as I'm doing now.

Does that sound right?

Thanks,
Russell

1 Like

Yes it does. More info about ACM here:

1 Like

Excellent. Thanks for the info!

1 Like