๐Ÿ” Android Security and Privacy

Certificate Pinning: Benefits and Limitations

Certificate pinning makes your app trust only specific keys for your servers, which blocks some man-in-the-middle attacks. Done carelessly, it can also lock every user out of your app when a certificate rotates. Here's when pinning is worth it and how to do it safely.

โœ๏ธ Yunok Tech ๐Ÿ“… Updated โฑ 3 min read ๐ŸŽฏ Advanced
On this page
  1. What pinning does and doesn't protect
  2. Pinning with Network Security Config
  3. Pinning with OkHttp
  4. Pinning safely
  5. Should you pin?
  6. Testing
  7. Frequently asked questions
  8. Conclusion

TLS already authenticates your server through trusted certificate authorities (CAs). Pinning adds a stricter rule: even a valid certificate from a trusted CA is rejected unless its public key matches one you've pinned. That protects against mis-issued certificates and some interception setups, at the cost of operational risk.

What pinning does and doesn't protect

How certificate pinning changes trust decisions Without pinning, any certificate chaining to a trusted CA is accepted, including a mis-issued one or one from a CA installed on a corporate or compromised device. With pinning, the connection is accepted only if the server's public key matches a pinned hash; otherwise it fails. Without pinning valid cert from your CA โ†’ โœ“ mis-issued cert, trusted CA โ†’ โœ“ (risk) interception proxy CA โ†’ depends With pinning key matches pin โ†’ โœ“ mis-issued cert โ†’ โœ— blocked your own rotated key, unpinned โ†’ โœ— outage!
Pinning blocks unexpected certificates, including your own if you forget to pin the new key.

Android apps targeting API 24+ already ignore user-installed CAs by default, which blocks many casual interception setups. Pinning additionally defends against mis-issued certificates from trusted CAs. It does not stop an attacker who controls the device and modifies your app.

Pinning with Network Security Config

res/xml/network_security_config.xmlXML
<network-security-config>
    <domain-config>
        <domain includeSubdomains="true">api.example.com</domain>
        <!-- Expiration: after this date pinning is NOT enforced, so old app versions keep working -->
        <pin-set expiration="2027-06-30">
            <!-- SHA-256 of the SubjectPublicKeyInfo: current key + at least one backup -->
            <pin digest="SHA-256">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</pin>
            <pin digest="SHA-256">BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=</pin>
        </pin-set>
    </domain-config>
</network-security-config>

The pin values above are placeholders. Compute real ones from your keys.

Pinning with OkHttp

CertificatePinnerKotlin
val pinner = CertificatePinner.Builder()
    .add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")   // current
    .add("api.example.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=")   // backup
    .build()

val client = OkHttpClient.Builder().certificatePinner(pinner).build()

Prefer Network Security Config when possible: it's declarative, applies app-wide, and supports an expiration date.

Pinning safely

  1. Pin public keys, not certificates, and preferably an intermediate CA or your own key that you control across renewals.
  2. Always include backup pins: a second key you hold offline, or another CA you might move to.
  3. Set an expiration date so very old app versions don't break permanently.
  4. Coordinate with whoever manages certificates, such as the backend team or CDN, and document the rotation process.
  5. Monitor pinning failures and have a plan, such as a forced update, if something goes wrong.

Should you pin?

Consider pinning

  • Banking, payments, high-value targets
  • You control the certificate lifecycle
  • Strong operational processes

Probably don't

  • Third-party APIs or CDNs you don't control
  • No process for coordinated key rotation
  • Small teams where an outage risk outweighs the benefit

For many apps, correct TLS, the default distrust of user CAs, server-side validation and Play Integrity provide better risk reduction per unit of operational effort.

Testing

  • Verify the pin values match the production chain before release, using a staging environment that mirrors production certificates.
  • Test that a deliberately wrong pin fails closed, and that debug overrides work for development proxies.

Frequently asked questions

Does pinning stop someone reverse engineering my API?

Not reliably. An attacker controlling their own device can modify the app to remove pinning. Pinning protects honest users' connections, not your API from its own clients.

What happens when my certificate renews?

If the public key changes and isn't in your pin set, connections fail for every app version with the old pins. That's why key reuse, backup pins and expirations matter.

Is pinning required by Google Play?

No. It's an optional hardening measure.

Conclusion

Certificate pinning adds protection against mis-issued or unexpected certificates, but brings real outage risk. If you pin, pin public keys with backups and an expiration, coordinate rotations, and monitor. Otherwise, rely on solid TLS defaults and server-side controls.

Next step: protect data at rest with Encrypted Data Storage in Android.

Official references

๐Ÿ“ฑ Apps built by Yunok Tech

Real Android apps on Google Play, free to download.

See all our apps โ†’

Ready to build real Android applications?

Security is easiest to get right when it is part of how you build from the first screen. Strengthen the Android fundamentals that secure, privacy-respecting apps are built on.

Move beyond theory and strengthen your Android development skills with Yunoktech's Android course. Learn core concepts, practical implementation, modern Android development techniques, and the reasoning behind building maintainable applications.

Explore the Android course and take your next step as an Android developer.

Share: LinkedIn X / Twitter WhatsApp