Protection against man-in-the-middle with a valid but wrong certificate
Certificate pinning protects mobile apps and API clients against man-in-the-middle attacks where an attacker presents a technically valid certificate, signed by a trusted certificate authority, that nonetheless does not belong to the real backend. We explain why public key pinning beats classic certificate pinning, how backup pins work, and how to avoid accidentally locking your own users out.
Table of Contents
- 1. The Threat Model: MITM with a Valid but Wrong Certificate
- 2. How Certificate Pinning Works
- 3. Certificate Pinning vs. Public Key Pinning
- 4. Why Plain Certificate Pinning Breaks on Certificate Renewal
- 5. Backup Pins: Insurance Against Planned and Unplanned Rotation
- 6. The History of HPKP and Why Browsers Abandoned the Concept
- 7. Implementation in Mobile Apps: iOS and Android Compared
- 8. The Lockout Risk: When Pinning Makes Your Own App Unusable
- 9. Best Practices for a Sound Pinning Strategy
- 10. Summary
- 11. FAQ
1. The Threat Model: MITM with a Valid but Wrong Certificate
Standard TLS validation checks whether a certificate was signed by one of the trusted certificate authorities baked into the operating system or browser, and whether it matches the requested hostname. That check reliably blocks self-signed or expired certificates, but it fails when an attacker holds a technically correctly signed certificate that still does not originate from the real operator.
Such certificates can come from several sources: a compromised or coerced certificate authority, an accidentally misissued certificate, or an extra root certificate installed on the device itself, the kind corporate MITM proxies, some antivirus software, or malicious configuration profiles rely on. In every one of these cases, the connection looks fully legitimate to the operating system even though traffic is actually being intercepted or tampered with.
2. How Certificate Pinning Works
Certificate pinning adds an extra expectation, hardcoded into the app, on top of normal TLS validation: alongside the regular chain check, the app compares the received certificate or its public key against a predefined list stored inside the app. If none of the stored pins match the actually received value, the app aborts the connection, even if the operating system would consider the certificate fully trustworthy.
On Android, this is configured declaratively through the Network Security Config, on iOS typically through libraries such as TrustKit or the system's own URLSession delegate method for certificate validation. Both approaches move the trust decision out of the system-wide certificate store and into the app itself, making the app independent of whatever extra root certificates happen to be installed on a given device.
<!-- res/xml/network_security_config.xml (Android) -->
<network-security-config>
<domain-config>
<domain includeSubdomains="true">api.mironsoft.de</domain>
<pin-set expiration="2027-01-01">
<!-- Current public key (SPKI hash) -->
<pin digest="SHA-256">k3rz9QcMH42ZMv/hHtP9Vt+u6+9Uv2wOX2Xr8pmqCbo=</pin>
<!-- Backup pin for the next planned rotation -->
<pin digest="SHA-256">9y5uK4iKz4Q4gCkH8Yjrl1J9Y4gU3nDy2sHwLxwvTuI=</pin>
</pin-set>
</domain-config>
</network-security-config>
3. Certificate Pinning vs. Public Key Pinning
With classic certificate pinning, the app stores a fingerprint of the entire certificate. That is simple to implement, but it carries a decisive drawback: as soon as the certificate gets renewed normally, after its validity period expires for example, the fingerprint changes entirely, even if the same private key gets reused. Every certificate renewal then forces an app update carrying the new pin, which quickly turns into an operational burden with short-lived certificates.
Public key pinning sidesteps this problem by storing not the certificate itself but the SPKI hash, the Subject Public Key Info fingerprint of the public key. As long as the same key pair gets reused across a certificate renewal, the pin remains valid regardless of how often the surrounding certificate itself gets renewed. For this reason, public key pinning is now considered the far more practical variant compared to plain certificate pinning.
4. Why Plain Certificate Pinning Breaks on Certificate Renewal
Breaking on renewal is not an edge case, it is the normal case: TLS certificates typically run for a few months up to a year at most and need regular renewal. Anyone pinning the full certificate fingerprint has to synchronize that cycle exactly with the app release cycle, which creates a tight, error-prone window given app store review times running from several days to weeks.
Even with perfect planning, the risk remains that users keep old app versions in service longer than expected, disabled automatic updates or a device offline for a while, for example. With a plain certificate pin, those users lose their connection to the backend abruptly after every certificate renewal, an effect that shows up far less often with public key pinning and long-lived, stable key pairs.
5. Backup Pins: Insurance Against Planned and Unplanned Rotation
A single pin is a single point of failure: if the underlying key needs to change unexpectedly, following a suspected compromise for example, every connection breaks until a new app version carrying the updated pin gets rolled out and installed by every user. That is why at least one backup pin belongs in any solid pinning configuration, ideally the public key of an already generated but not yet active next certificate.
The backup pin should represent a key kept entirely independent from the currently used key, offline or in a separately secured key store for example, so an attacker who compromises the active key does not automatically gain the backup key too. Without that separation, the backup pin loses much of its security value, since both keys would end up compromised together in a real incident.
6. The History of HPKP and Why Browsers Abandoned the Concept
For classic web pages, HTTP Public Key Pinning, or HPKP, existed as a header-based counterpart to mobile pinning, introduced by browsers around 2015. A server could specify via header which public key pins to expect on future connections, cacheable over several weeks. In practice, this repeatedly produced exactly the lockout problem pinning was meant to prevent: misconfigurations or server issues locked users out permanently, with no easy way to fix it.
Given that high risk against comparatively modest added protection over Certificate Transparency and modern CA controls like CAA records, every major browser eventually removed HPKP from its implementation. This assessment applies only partially to mobile apps, since pinning there is deployed more deliberately, under the direct control of the app developer, against a clearly defined backend, rather than browser-wide against arbitrary sites the user never chose.
7. Implementation in Mobile Apps: iOS and Android Compared
On Android, pinning can be implemented entirely declaratively through the Network Security Config shown earlier, without writing any custom certificate validation code, which reduces sources of error. Alternatively, networking libraries such as OkHttp offer their own CertificatePinner that can be configured programmatically and provides extra flexibility, for dynamically loaded pin sets for example.
On iOS, the TrustKit library frequently handles this task, offering comparable declarative configuration through the app's Info.plist and additional reporting features that can send failed pin validations back to a backend. Anyone wanting to avoid an extra library can implement the check directly inside the URLSession delegate method for server trust validation, which grants more control but also more responsibility for correct error handling.
8. The Lockout Risk: When Pinning Makes Your Own App Unusable
The biggest practical risk with certificate pinning is not a missed attack, it is a self-inflicted outage. Because pins are hardcoded into the shipped app, a faulty or stale configuration cannot simply be fixed with a server-side update, it requires a full app update including store review and, crucially, actual installation by users. Until then, affected users lose all connectivity to the backend.
It gets especially dangerous during an unplanned emergency rotation, following a suspected key compromise for example, when no matching backup pin exists. In that situation, the development team faces a choice between temporarily disabling pinning server-side, which erases the original security benefit, or locking users out entirely until the next app update, which can become business critical for security-sensitive apps, in banking for example.
9. Best Practices for a Sound Pinning Strategy
A resilient pinning strategy prefers pinning the public key of an intermediate or even root certificate of the certificate authority in use rather than the leaf certificate, since those keys rotate far less often and thereby reduce the rotation frequency demanded of the app's own pins. On top of that, at least two independent backup pins should be stored, ideally for already prepared but still inactive keys from different sources.
Security and mobile teams should plan pin rotations together and rehearse them against a test environment with realistic certificate swaps before every production rollout, rather than relying on theory alone. A server-side fallback mechanism that allows a controlled, time-limited disabling of pinning in an emergency, through a remote configuration flag for example, prevents a permanent lockout in a real incident without weakening the protection during normal operation.
| Approach | What Gets Pinned | Advantage | Risk |
|---|---|---|---|
| Certificate pinning (leaf) | Fingerprint of the entire end-entity certificate | Very precise control | Breaks on every certificate renewal |
| Public key pinning (leaf) | SPKI hash of the public key | Survives renewal with the same key | Breaks on key change without a backup pin |
| Public key pinning (intermediate) | SPKI hash of the CA's intermediate certificate | Rarely changes, low rotation burden | Does not protect against a compromised CA itself |
| Pinning without a backup pin | Only a single current pin | Simplest configuration | High lockout risk on emergency rotation |
Mironsoft
Security audits, OWASP-compliant hardening, and secure architecture
Applications that actually hold up against a real attack attempt?
We review existing applications for classic OWASP vulnerabilities, insecure authentication, and missing input validation, then build an architecture that structurally reduces attack surface instead of just patching individual symptoms.
Security Audit
Systematically checking OWASP Top 10, auth flows, and input validation for vulnerabilities.
Secure Architecture
Building rate limiting, encryption, and access controls correctly from the ground up.
Incident Readiness
Establishing logging, monitoring, and response processes for when things go wrong.
10. Summary
Certificate Pinning: The Essentials at a Glance
Threat
Man-in-the-middle with a valid but fraudulent certificate.
Better Method
Public key pinning instead of a full certificate fingerprint.
Safeguard
At least one independent backup pin for the next rotation.
Biggest Risk
App lockout when a backup pin is missing during unplanned rotation.