What Is Certificate Pinning?
Learn what certificate pinning is, when it makes sense to use it, the significant risks involved, and modern alternatives that may better suit your needs.
Learn what certificate pinning is, when it makes sense to use it, the significant risks involved, and modern alternatives that may better suit your needs.
Certificate pinning is a security technique where a client application is configured to only accept specific cryptographic certificates or public keys when connecting to a server, rather than accepting any certificate signed by a trusted Certificate Authority (CA).
You’re likely familiar with the lock icon in your browser’s address bar when visiting an HTTPS site. This lock indicates that:
Third parties who cannot read your encrypted traffic include:
Standard HTTPS has a significant trust assumption: it trusts any certificate signed by any of the hundreds of Certificate Authorities in your device’s trust store.
This creates several attack scenarios:
Compromised Certificate Authority If an attacker compromises a CA (or convinces one to issue a fraudulent certificate), they can impersonate any website. This has happened—DigiNotar’s compromise in 2011 led to fraudulent Google certificates being issued.
Government-Mandated Interception Some governments require organizations to install root certificates that enable traffic interception. Corporate proxy servers often do the same for “security monitoring.”
Malicious Root Certificate Installation Malware or social engineering can trick users into installing rogue root certificates, enabling man-in-the-middle attacks on all HTTPS traffic.
In each case, your browser sees a “valid” certificate chain and shows the reassuring lock icon—even though you’re not actually talking to the real server.
Certificate pinning adds an additional check: the client verifies not just that a certificate is valid, but that it matches a specific certificate or public key the application expects.
Standard HTTPS:
Is certificate signed by trusted CA? → Yes → Allow connection
With Pinning:
Is certificate signed by trusted CA? → Yes
Does certificate match our pinned value? → Yes → Allow connection
You can pin at different levels:
Here’s how certificate pinning looks in a modern iOS app using URLSession:
// iOS Certificate Pinning with URLSession
class PinnedSessionDelegate: NSObject, URLSessionDelegate {
// SHA256 hash of the server's public key
let pinnedPublicKeyHash = "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard let serverTrust = challenge.protectionSpace.serverTrust,
let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
// Extract and hash the public key
let publicKey = SecCertificateCopyKey(certificate)
let publicKeyData = SecKeyCopyExternalRepresentation(publicKey!, nil)! as Data
let hash = SHA256.hash(data: publicKeyData)
let hashString = Data(hash).base64EncodedString()
if hashString == pinnedPublicKeyHash {
completionHandler(.useCredential, URLCredential(trust: serverTrust))
} else {
// Pin validation failed - possible MITM attack
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
}
For Android with OkHttp:
// Android Certificate Pinning with OkHttp
val client = OkHttpClient.Builder()
.certificatePinner(
CertificatePinner.Builder()
.add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.add("api.example.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=") // Backup pin
.build()
)
.build()
Certificate pinning is most appropriate for:
High-Security Mobile Apps Banking, healthcare, and financial apps where the threat model includes sophisticated attackers who might compromise CAs or install rogue certificates.
Apps Handling Extremely Sensitive Data Applications where even a theoretical MITM attack is unacceptable, such as secure messaging apps or cryptocurrency wallets.
Controlled Environments Internal enterprise apps where you control both the client and server, and can manage certificate updates reliably.
Certificate pinning has fallen out of favor for most applications due to significant operational risks:
If your pinned certificate expires or you need to rotate it, and users have an old version of your app with the old pin, those users are completely locked out. They can’t connect at all—not even to download an update.
Scenario: Certificate Rotation Gone Wrong
Day 1: App v1.0 ships with Pin A
Day 90: Certificate expires, you deploy new cert with Pin B
Result: All users on v1.0 cannot connect to your servers
They can't update because the update check also fails
Only fix: Users must manually reinstall the app
If your private key is compromised, you need to rotate certificates immediately. With pinning, this breaks all existing clients until they update—which they can’t do if the update mechanism is also pinned.
Modern architectures often use CDNs, load balancers, or multi-cloud setups where certificates may change. Pinning makes infrastructure changes extremely difficult.
HTTP Public Key Pinning (HPKP) was a web standard that let websites tell browsers to pin their certificates. Chrome removed HPKP support in 2018 because the risks outweighed the benefits:
The security community has largely moved toward alternatives that provide similar protection with fewer operational risks:
Certificate Transparency requires CAs to publicly log all certificates they issue. This means:
CT is now required by major browsers and provides protection against CA compromise without client-side pinning risks.
You can instruct browsers to enforce Certificate Transparency for your domain:
Expect-CT: max-age=86400, enforce, report-uri="https://example.com/ct-report"
Certificate Authority Authorization (CAA) DNS records specify which CAs are allowed to issue certificates for your domain:
example.com. CAA 0 issue "letsencrypt.org"
example.com. CAA 0 issuewild ";"
This prevents any CA except Let’s Encrypt from issuing certificates for your domain, reducing the attack surface.
Rather than pinning on the client, monitor for fraudulent certificates:
For most applications in 2026, we recommend:
If you do implement pinning, always include backup pins and have a tested certificate rotation process. Consider pinning to intermediate CA certificates rather than leaf certificates to give yourself more flexibility.