[Problem] Updating server's SSL certificate breaks app with SSL pinning


Backstory: I implemented SSL pinning in my iOS app. The thing is that we’re using an letsencrypt ssl certificate on our server where we have our api. And since letsencrypt’s certificate expires every 3 months, the app will stop working every 3 months as well if we don’t issue an update with the new certificate inside. For this case I’ve built a smart mechanism of refetching fresh ssl certificates by the app.

The issue: when a new ssl cert is auto-generated by letsencrypt, the current cert, which is in the app stops being served with responses. Even though the current cert is still valid. Example:
Our web cert is valid from Mar 6 till Jun 6. The app fetched and stored it.
We manually updated our web cert today and it’s now valid from Mar 14 till Jun 14. But the app stopped working. Even though it still has a perfectly unexpired(valid?) cert till Jun 6. And until the cert is updated in the app, it won’t be able to do API calls.


  1. Why aren’t my API calls served?
  2. The premise of SSL pinning is to handle request only with an identical cert as the server does?
  3. Is it possible somehow to use the current unexpired (and valid a second ago) certificate and update it to a new one in a week for example? Instead of making the app useless right at the moment the server’s certificate got updated? Because in real life who knows when the app will have the opportunity to update the cert to a new one.

Certificate pinning is usually performed against the server’s public key, not the certitificate itself. In order for the pin to remain valid, you need to issue new certificates using the same public/private key pair. However, the default behavior of certbot and many other clients is to generate a new key pair for every certitificate, which will break your pin.

What client are you using?

Thanks! I’m using iOS with Alamofire.

Sorry, I meant what ACME client are you using to get certificates? Certbot or a different one?

I’m using whatever Google App engine uses, since that’s where I host my API

Ah, unfortunately they don’t give you any control on whether you rotate the keypair or not. :frowning:

If you want to use pinning with GAE you would have to manually manage your certificates, so you control if/when the key is rotated instead of using their automatic Let’s Encrypt integration.

If you really want to continue using public key pinning, one option you could try is pinning against a root or intermediate certificate’s public key, which won’t change nearly as frequently. A downside of that approach is an attacker who manages to get a certificate for your domain could bypass certificate pinning (because they would have a certificate signed by one of the pinned public keys).

If you want to pin directly to your server’s certificate, you should be able to add multiple public keys to pin against (as a safeguard in case one of your certificates needs to be replaced quickly). Although, considering @Patches’s comment that GAE doesn’t let you control the keys with their automatic Let’s Encrypt integration, I don’t think this option is feasible for you unless you manually manage your keys/certificates.

1 Like

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