8

We use cert pinning when developing for iOS and Android. We use regular 12 month certs that are paid for.

We recently switched to Lets Encrypt (LE) for our general website certificates and would like to use LE certs in our mobile apps as well.

The issue is our current certificate pinning framework requires the app to be resubmitted with each new certificate, so if using LE this would be every 3 months (the max length of a LE cert). This is not practical.

I have researched alternatives and the most viable seems to be public key hashing. So query the server get the cert, extract the public key and compare to a hash we have store in the app binary.

This method means we would manually create the Certificate Signing Request (CSR) used for LE, as currently it just creates a new one with every certificate request, in order to retain the original key pairing.

My question: Is this public key hashing the best solution for a long term certificate pinning inside a mobile app?

4
  • 5
    Pinning the key will work. However one could also pin the CA (ie the LE CA cert) and trust the CA to not maliciously issue.
    – SEJPM
    Sep 21, 2017 at 14:24
  • 1
    You can just use a self-signed certificate with long expiry date and use it for app connections
    – PyQL
    Jan 18, 2018 at 7:10
  • 1
    @Trickycm did you end up pining the public key?
    – ahbou
    Feb 20, 2018 at 16:27
  • @ahbou yes we did, using a custom CSR when it needed updating. We added key rotation into regular releases to force update the public key at fixed intervals we controlled. Feb 2, 2021 at 8:55

1 Answer 1

1

TLDR; either perform certificate creation and app submission within the lifetime of the issued certificate, or; don't use Let's Encrypt, or; don't use pinning in the app and instead apply DANE/DNSSEC and CAA.

Explained:

The normal method for embedded apps (like iOS and Android) that use Certificate pinning is to have multiple pinned Certificates with no (or little) overlapping dates, so the notBefore of the next valid pinned Certificate is the same as the previous valid pinned Certificate notAfter date.

By default Let’s Encrypt certificates are intentionally backdated notBefore by 1 hour from the request. It's up to the CA to decide the notBefore and notAfter dates and do not support the methodology used for embedded apps.

Let's encrypt allows you to generate a CSR, which is the best way to customise the Certificate they issue, here is an example from my own production app:

Request Certificate 1:

certbot certonly \
  --dry-run \
  -n \
  --dns-route53 \
  --agree-tos \
  --csr "<path to my CSR>" \
  --register-unsafely-without-email \
  --no-eff-email \
  --dns-route53-propagation-seconds 300 \
  --cert-path "<path to store the issued X.509 Leaf Certificate>" \
  --key-path "<path to store the private key>" \
  --fullchain-path "<path to store the issued X.509 Leaf Certificate and the chain of intermediate and CA Certificates as a bundle>" \
  --chain-path "<path to store the chain of intermediate and CA Certificates as a bundle minus the actual issued X.509 Leaf Certificate>" \
  -d sub.domain.tld

Request another Certificate for the same doamin, without removing the original, and run 2 months after the first:

certbot certonly \
  --- same as above ---
  --duplicate \
  --force-renewal \
  -d sub.domain.tld

The second certificate is issued with a notBefore 2 months after the first.

Important to note that the CSR format (PKCS#10) doesn't have any fields to put these dates so it's still depending on the Let's Encrypt hidden decisions that you do not control to get this result.

It would be more beneficial for you to go back to your threat model and better understand why certificate pinning was implemented. Mostly pinning is being removed for better suited options, because pinning used to be a solution for many things it was not suited and today we have options like TLSA/DANE, DNSSEC, and using CAA records to completely verify a chain of trust to the expected trust anchor.

If you find that your threat model indicates pinning is the best mitigation for whatever risks you have identified, then you will need to find a CA that can issue Leaf Certificates that are future dated (notBefore) and have multiple pinned certificates deployed with your app.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .