Hello,
We recently implemented SSL pinning in our iOS app (Objective-C) using the common approach of embedding the server certificate (.cer) in the app bundle and comparing it in URLSession:didReceiveChallenge:. This worked fine initially, but when our backend team updated the server certificate (same domain, new cert from CA), the app immediately started failing because the bundled certificate no longer matched.
We’d like to avoid shipping and updating our app every time the server’s certificate changes. Instead, we are looking for the Apple-recommended / correct approach to implement SSL pinning without embedding the actual certificate file in the app bundle.
Specifically:
. Is there a supported way to implement pinning based on the public key hash or SPKI hash (like sha256/... pins) rather than the full certificate?
. How can this be safely implemented using NSURLSession / SecTrustEvaluate (iOS 15+ APIs, considering that SecTrustGetCertificateAtIndex is deprecated)?
. Are there Apple-endorsed best practices for handling certificate rotation while still maintaining strong pinning?
Any guidance or code samples would be greatly appreciated. We want to make sure we are following best practices and not relying on brittle implementations.
Thanks in advance!
Are there Apple-endorsed best practices for handling certificate rotation while still maintaining strong pinning?
No. TLS pinning is very much a two-edge sword, and you’ll have to make your own determination as to whether you want to implement it or not [1].
On the technical side of this, there are two ways you can approach TLS pinning:
- Starting with iOS 14, App Transport Security supports various declarative options. For more on that, see the
NSPinnedDomains
property. - If that’s not sufficient, you can modify the technique you’re already using to pin the public key. Call
SecTrustCopyCertificateChain
to get the certificate chain from your trust object. CallSecCertificateCopyKey
to get the public key from a certificate. CallSecKeyCopyExternalRepresentation
to get the raw bytes from the public key.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] TLS pinning will cause your app to fail in the presence of TLS inspection. While some uses of TLS inspector are malicious, some are absolutely legitimate. For example, various enterprises deploy TLS inspection as part of their security policy. If you deploy TLS pinning, your app won’t work in such environments.