How to recreate let's encrypt certificate with public key from the past?

So what we have is an invalid let’s encrypt certificate, when we try to renew it, public key changes. Is there a way to preserve the old public key? Our clients have it implemented for SSL pinning purposes.

certbot certificates shows:

Certificate Name: domain.com-0001
Domains: domain.com api.domain.com beta-api.domain.com beta.domain.com demo.domain.com
Expiry Date: 2018-04-16 11:58:34+00:00 (INVALID: EXPIRED, REVOKED)
Certificate Path: /etc/letsencrypt/live/domain.com-0001/fullchain.pem
Private Key Path: /etc/letsencrypt/live/domain.com-0001/privkey.pem

Renewal actually works, but it generates a new SHA256. Is it possible to preserve the old one? Please help, thanks!

My domain is:
api.domain.com

I ran this command:
certbot --nginx renew

It produced this output:
Renewed certificates, but different SHA256 pin.

My web server is (include version):
Ubuntu server 16.04

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

My hosting provider, if applicable, is:
AWS

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.

Use a different ACME client.

Certbot makes it it really hard to do what you want: https://github.com/certbot/certbot/issues/3788 , https://jkphl.is/articles/certbot-http-public-key-pinning-hpkp/

acmetool is one such client that allows you to re-use the certificate key (but it doesn’t do it by default).

I’m going to be working on this much-delayed feature next week, but I agree with the suggestion to use another ACME client for now. Right now the only way to do this with Certbot is to create a CSR using the old key and then use --csr (which won’t work with certbot renew, so it’s less convenient).

1 Like

Can you please provide me with some pointers on how to create a CSR using the old key? If I understand correctly, we are talking about old private key, which I have stored in /etc/letsencrypt/archive/domain/privkey.pem?

You’ll need to use the openssl req command.

You can use this documentation to see the usage: https://support.rackspace.com/how-to/generate-a-csr-with-openssl/#create-a-csr

You are right that using privkey.pem would be correct, however be careful as that is a symlink that is changed after Certbot does automatic renewal. So maybe verify the private key is the one that generates the right HPKP hash before you do it.

Once you have a CSR, though, you can re-use it all you want. It does not need to be regenerated at any point unless you want to change the list of domains or change the private key. So you might consider just copying a CSR from /etc/letsencrypt/csr if one is suitable.

I am wondering, when I create CSR or use the existing one, what exactly is sudo certbot certonly --csr /etc/letsencrypt/csr/csr-certbot.pem suitable for? Thisis not renewal, but will it make my certificate valid?

It will obtain a new certificate using the key specified in the CSR and save the new certificate in the current directory, rather than under /etc/letsencrypt as certbot renew does. (Also, running certbot renew will not re-use this CSR.) The certificates obtained with certbot certonly --csr aren't tracked for renewal purposes by Certbot.

1 Like

Ok, let’s say I just need previous state, with last SHA256 pin, then I can use this, right? Before renewal I can manually build new ones, by then it won’t matter if the certificate is different. But you said that certonly doesn’t save to live folder, shoul I run in in /etc/letsencrypt/live/ folder to make changes to the currently active certificate?

If you refer to a new CSR, that should not be necessary - unless the names have changed.

That sounds like it may cause more trouble than it can be resolving.
Just update the lines in the vhost config to point to wherever you place your "certonly" certs.

@rg305 @_az @schoen this worked just fine, however, grade fell from A to B, but additional issue is that we get javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. on our clients. SHA256 pin is exactly the same.

Am I missing something here?

You are failing to configure the intermediate certificate in your webserver, probably.

If, previously, you used fullchain.pem (which contains both your certificate followed by the intermediate), you need to ensure that you are still sending the intermediate somehow.

If your domain is what I think it is, then it looks like you’re solved the intermediate issue an have an A+ now.

If you show the domain or B report text, we can maybe see more and help more.

try:
openssl s_client -connect your.server.ip:443 -servername server.name -showcerts

Found the problem. I just ran cat 0000-cert.pem 0000-chain.pem > 0000-fullchain.pem and pointed created file to nginx. Now the grade is A+ and chain is complete.

Thank you guys for all of your help, I admit that this was a new experience for me. Anyways, we will reconsider using SSL pinning in the future and after this I also advise those who are planning to use it, to be extremely catious.

Cheers :beer:

There's nothing inherently difficult about reusing a private key, it's just that Certbot doesn't have a convenient way to do it, which is mainly due to my neglecting to finish my implementation of that feature from a year ago. Once Certbot has that feature there should be a simple option that will simply result in the same private key being used with certbot renew.

However, there has been some sentiment against pinning for other reasons, with Google deciding to deprecate HPKP support in Chrome (apparently because they've decided to trust Certificate Transparency to detect misissuance, and because some people were making mistakes with pinning that led to people getting locked out of web sites). Pinning is still popular for other use cases like an internal API, but in many of those cases there's no security benefit from using a public CA!

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.