Certificate Pinning: What It Is, Mechanism, and Pinning Methods

Author: IT Sectr Published: 2026-03-09 Reading time: 8 min

Certificate Pinning is a mechanism for fixing a server’s certificate or public key, where an application uses a pre-known fingerprint to verify an HTTPS connection. Unlike the standard chain of trust through a CA, pinning ensures that even a compromised certificate authority cannot issue a fraudulent certificate for your domain. According to OWASP MSTG (2025), Certificate Pinning is listed as a mandatory control for L2 protection level applications. Implementation involves storing certificate hash fingerprints in code and verifying them on each request.

Key Takeaways

  • Certificate Pinning — a technique where an application only trusts a certificate with a pre-known fingerprint, ignoring the entire CA chain
  • Public Key Pinning — an alternative that pins only the public key, simplifying rotation when the certificate is changed
  • HPKP (HTTP Public Key Pinning) — a deprecated standard at the HTTP header level, not recommended for new projects
  • Backup pins — reserve fingerprints that ensure connection continuity when the primary certificate is changed or expires
  • Implementation on iOS via SecTrustEvaluate, on Android via CertificatePinner in OkHttp or TrustManager

What Is Certificate Pinning?

Certificate Pinning is a security technique where an application stores the fingerprint of a trusted certificate and uses it as the sole criterion for establishing an HTTPS connection. In the standard TLS model, the client verifies that the server’s certificate is signed by a trusted root CA — any of the hundreds of pre-installed certificate authorities on the system. Certificate Pinning replaces this chain with a direct check: the certificate must match the stored sample or contain the expected public key.

The problem with the standard model became evident after CA compromise incidents — DigiNotar (2011), Comodo (2011), TrustCor (2022). If a CA issues a fraudulent certificate for your domain, the browser or application accepts it as valid. Certificate Pinning prevents this attack: even a perfectly signed fraudulent certificate will be rejected because its fingerprint does not match the one pinned in the application.

The term pinning comes from pin — a fastener: the developer locks in a trusted certificate, and any deviation from it blocks the connection. According to research from Mitre CWE-295, improper certificate validation remains one of the top-10 most dangerous security errors in mobile applications, and Certificate Pinning is a direct method of preventing it.

History and Evolution of Certificate Pinning

Originally, Certificate Pinning was used in browsers through the HPKP (HTTP Public Key Pinning) mechanism, standardized in RFC 7469. The developer sent an HTTP Public-Key-Pins header with hashes of expected keys, and the browser stored them for a specified period. However, HPKP turned out to be dangerous: a single configuration error could lock a site out for months. In 2018, Chrome discontinued support for HPKP, and the current standard became client-side implementation — inside a mobile application or browser extension.

How Does Certificate Pinning Work?

The Certificate Pinning process involves three key stages: fingerprint calculation, connection verification, and error handling. During preparation, the developer obtains the SHA-256 hash of the production server’s certificate or public key. For GDPR- and PCI DSS-compliant applications, it is also required to pin the fingerprints of intermediate CAs in the chain.

With each HTTPS request, the application intercepts the TLS authentication callback, extracts the server’s certificate, and computes its SHA-256 hash. This hash is compared against the stored list of trusted fingerprints. If a match is found — the connection proceeds. If not — the application must terminate the connection and report an error without revealing implementation details to an attacker.

kotlin
fun validateCertificate(certificate: X509Certificate,
    expectedHash: String): Boolean {
    val digest = MessageDigest.getInstance("SHA-256")
    val hash = Base64.encodeToString(
        digest.digest(certificate.publicKey.getEncoded()),
        Base64.DEFAULT
    ).trim()
    return hash == expectedHash
}

The function takes an X509Certificate object from the server and the expected hash. It first extracts the certificate’s public key, computes the SHA-256 hash, and encodes it in Base64. The result is compared against the expected fingerprint. In production, you should add verification against an array of 2–3 fingerprints to support rotation.

Certificate Pinning vs Public Key Pinning

When implementing pinning, you need to choose which cryptographic object to lock in. Certificate Pinning binds to the X.509 certificate itself — its serial number, validity period, and the entire chain. Public Key Pinning locks only the public key inside the certificate, ignoring other fields. This choice significantly impacts operational costs.

CriterionCertificate PinningPublic Key Pinning
Pinning ObjectEntire X.509 certificateRSA/ECDSA public key
RotationRequires update on each reissuanceDoes not change when the certificate is renewed with the same key
SecurityMaximum precision bindingLess sensitive to details
FlexibilityLow — certificates change every 1–2 yearsHigh — keys can last 5–10 years
RecommendationFor critical systems with controlled updatesFor most mobile applications and APIs

Public Key Pinning is the preferred choice for most projects. Server public keys generally remain unchanged when a certificate is reissued — the company simply signs the old key with a new certificate. This means the application does not require an update after a certificate change if the key pair has not changed. Certificate Pinning, on the other hand, is recommended for scenarios where the developer fully controls both the server and client code, such as in enterprise applications with a strict update cycle.

Trust On First Use (TOFU)

TOFU is a strategy where Certificate Pinning is not configured in advance but remembers the certificate on the first connection to the server. This approach is convenient for applications that do not know in advance which server they will connect to. The downside is vulnerability to an initial attack: if the first connection is intercepted, a fraudulent certificate will be accepted as trusted. TOFU is used in SSH connections and some P2P protocols.

Implementation on iOS and Android

On both platforms, Certificate Pinning is implemented by intercepting the TLS connection at the network stack level. On iOS, the URLSession delegate or Alamofire ServerTrustManager is used. On Android, the preferred method is OkHttp CertificatePinner, which is built into popular HTTP clients and supports configuring multiple fingerprints for each domain.

swift
func validate(serverTrust: SecTrust,
    pinnedHash: String) -> Bool {
    guard let certificates = SecTrustCopyCertificateChain(serverTrust)
        as? [SecCertificate] else { return false }

    for certificate in certificates {
        let data = SecCertificateCopyData(certificate)
        var hash = Data(repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
        data.withUnsafeBytes {
            CC_SHA256($0.baseAddress,
                CC_LONG(data.count), &hash)
        }
        if hash.base64EncodedString() == pinnedHash {
            return true
        }
    }
    return false
}

In the Swift function, the certificate chain is extracted from serverTrust, a SHA-256 hash is computed for each certificate, and the result is compared against the expected one. Iterating through all certificates in the chain allows pinning at the intermediate CA level — if an intermediate certificate matches, the connection is accepted. This provides flexibility during leaf certificate rotation.

Custom TrustManager for Android

If the application does not use OkHttp, Certificate Pinning can be implemented through a custom X509TrustManager. This approach requires more code but gives full control over the verification process. The TrustManager overrides the checkServerTrusted method, where the developer manually verifies the server certificates and decides whether to trust them. It is recommended only for specific scenarios where the OkHttp library is unavailable.

Common Mistakes in Certificate Pinning Implementation

The most common mistake is the absence of backup pins. A developer includes a single certificate fingerprint, and when it expires, users massively lose connectivity. The minimum acceptable configuration is two fingerprints: the current certificate and a backup. Ideally three: the current one, a backup, and the root CA fingerprint as a fallback.

The second mistake is storing pins in plain text in code. An attacker with access to an APK or IPA can easily extract and replace fingerprints. Hash obfuscation is recommended: split the string into parts, store in encrypted resources, or compute at runtime. For Android, ProGuard with string constant obfuscation is effective.

The third mistake is pinning at the development certificate level. Development and production certificates are usually different, but developers often forget to switch pins when building a release. The result is that the production application cannot connect to the server. The solution is separate pin configurations for debug and release via BuildConfig or flavor-specific resources.

  • Ignoring certificate chain — checking only the leaf certificate without considering intermediate CAs, which breaks the connection during rotation
  • Hardcoded dates — hardcoded certificate expiration dates that do not change after updates
  • No monitoring — absence of alerts for Certificate Pinning errors, causing issues to only be discovered from users
  • TOFU without validation — using Trust On First Use without additional verification, allowing the first MITM attack to pin a fraudulent certificate

Frequently Asked Questions

How is Certificate Pinning different from SSL Pinning?

SSL Pinning is a general term for binding to an SSL/TLS certificate. Certificate Pinning is a specific implementation that locks in the X.509 certificate itself, not just the public key. The difference is in the binding object: certificate vs key.

How to safely store certificate fingerprints in an application?

It is recommended to store hashes in resources with obfuscation via ProGuard (Android) or encrypted through Keychain (iOS). Avoid storing pins in plain text in strings.xml or Info.plist without encryption.

How often should pinned fingerprints be changed?

With every certificate change on the server. It is recommended to add a new fingerprint as a backup pin 3–6 months before the current one expires, and remove the old one after rotation. At least one backup pin is mandatory.

Can Certificate Pinning be disabled for debugging?

Yes, through conditional compilation: pinning is disabled in the debug build and enabled in the release build. Use BuildConfig.DEBUG on Android or #if DEBUG on iOS for switching. Never do this through a runtime flag accessible to the user.

What to do if a certificate is compromised?

Immediately release an application update with new fingerprints and publish it in the stores. Use a forced update mechanism. If the backup pins included the backup CA fingerprint, you can temporarily switch to a different domain with a different certificate.

Summary

  • Certificate Pinning — locking in a trusted certificate or its public key to protect against MITM attacks via fraudulent CAs
  • Two approaches — certificate pinning (strict, to the certificate) and public key pinning (flexible, to the public key)
  • Backup pins are mandatory — at least 2 fingerprints to ensure continuity during certificate rotation
  • OkHttp CertificatePinner — standard implementation approach on Android with support for multiple pins
  • URLSessionDelegate — primary approach on iOS with manual SecTrust verification and SHA-256 hashes
  • Common mistakes — missing backup pins, storage without obfuscation, debug/release configuration confusion
  • Recommendation — use public key pinning for most projects and Certificate Pinning only for critical systems

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also