Certificate Pinning: Implementation and Pitfalls
Certificate pinning hardens a client against a compromised or coerced certificate authority by constraining which certificates or public keys it will trust for a given host, beyond what the normal TLS trust chain provides. It's a real defense against CA-level compromise and on-path interception, but it's also one of the most common causes of self-inflicted mobile app outages when certificate rotation isn't planned for. This article covers what to pin, how to implement it, and the operational discipline it demands.
What pinning actually protects against
Standard TLS validation trusts any certificate issued by any CA in the client's trust store. That's a large trust surface — a compromised CA, a mis-issued certificate, or a malicious enterprise root installed on a device (common in some MITM-based traffic inspection setups) can all produce a certificate that passes normal validation for a domain it shouldn't be able to vouch for.
Pinning narrows that trust to a specific certificate, public key, or CA that the app developer explicitly expects for their own backend, so a technically valid-but-wrong certificate — even one that chains to a trusted root — gets rejected. This is most valuable for high-value mobile apps (banking, secure messaging) and API clients where an attacker with a rogue certificate would otherwise be indistinguishable from the legitimate server.
What to pin: leaf, intermediate, or public key
There are several levels at which pinning can operate, and the choice has direct operational consequences.
| Pin target | Security | Rotation friction | Notes |
|---|---|---|---|
| Leaf certificate | Highest — exact certificate must match | Highest — breaks on every renewal | Rarely used alone; too brittle for routine cert rotation |
| Public key (SPKI) of leaf | High — same key pair required | Lower — survives re-issuance with same key | Common approach; pin survives cert renewal if key is reused |
| Intermediate CA | Moderate — trusts any leaf from that intermediate | Low — survives leaf rotation entirely | Good balance for orgs that control their CA relationship |
| Root CA | Lowest meaningful pin — trusts entire CA hierarchy | Lowest | Barely stronger than default trust store; limited value |
Implementation pattern: SPKI pinning on mobile
Pinning the Subject Public Key Info (SPKI) hash of the leaf certificate is the most common production pattern, since it lets you rotate the certificate itself (a routine event every 90 days to a year) without invalidating the pin, as long as the underlying key pair is reused. Both major mobile platforms provide native or widely adopted library support for this.
Extracting an SPKI pin with openssl (used to generate the pin value shipped in an app)
# Get the SPKI SHA-256 hash for pinning, in the base64 format most
# pinning libraries (e.g. TrustKit, OkHttp CertificatePinner) expect
openssl s_client -connect api.example.com:443 -servername api.example.com </dev/null 2>/dev/null \
| openssl x509 -pubkey -noout \
| openssl pkey -pubin -outform der \
| openssl dgst -sha256 -binary \
| openssl enc -base64Always pin more than one certificate
The single most common pinning failure is shipping exactly one pin. When that certificate is renewed — even with the same key, but especially with a new key or a CA migration — every installed app instance that hasn't been updated loses the ability to connect, because there is no fallback pin to validate against. This has caused real, publicized outages for major apps.
The standard mitigation is to pin at least two independent targets: the current leaf/key and a backup key that is generated and safely stored but not yet deployed, so the backup can be rotated into production before the app needs to update. Some implementations also pin an intermediate or the CA itself as a broader fallback, accepting the lower security margin in exchange for resilience.
- •Ship at least a primary and a backup pin, ever
- •Generate the backup key pair in advance and keep it offline until needed
- •Track certificate expiry against your app release cadence — if app updates take months to reach most users, plan pin rotation with that lag in mind
- •Always include a non-pinned emergency killswitch (server-driven config flag) that can disable pinning enforcement remotely if a rotation goes wrong
Failure modes and fallback design
Because a strict pinning failure means the app refuses to connect at all, the failure mode has to be deliberately designed, not left as a hard crash. Most production implementations treat a pin validation failure as a distinct error path: fail the specific request, surface a clear error to the user, and — critically — report the failure to a monitoring endpoint over an unpinned channel if possible, so operators can detect rotation problems quickly rather than discovering them through app store reviews.
Pinning also interacts badly with legitimate TLS-terminating middleboxes some enterprise and regulated environments require (corporate proxies, certain security appliances). Decide up front whether your threat model needs to defeat those environments too, since a hard pinning failure there is functionally identical to blocking your own users on managed corporate networks.
When not to pin
Pinning adds real operational risk in exchange for a specific, narrow threat model (CA compromise, targeted MITM). For a typical web application served over standard browser TLS, pinning is largely obsolete — HTTP Public Key Pinning (HPKP) was deprecated and removed from browsers precisely because of the rotation-outage problem described above, and Certificate Transparency plus modern CA governance now covers much of the same threat at lower operational cost.
Pinning remains most justified in client contexts you fully control the release cycle for and where the stakes of interception are high: mobile banking and payments apps, secure messaging clients, and machine-to-machine API clients with controlled deployment. Outside those cases, the maintenance burden usually outweighs the marginal security gain.
References
Primary sources for the material above. Standards are cited by identifier so they stay findable as publishers reorganise their sites.
- RFC 7469 — Public Key Pinning Extension for HTTP (HPKP; historical/deprecated, useful for threat model background)
- OWASP Mobile Application Security Testing Guide — Certificate Pinning
- NIST SP 800-52 Rev. 2 — Guidelines for the Selection, Configuration, and Use of TLS Implementations