DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • The 30 Seconds Before a Mobile App Crash: The Evidence Most Systems Never Capture
  • The Request Timed Out, But the Payment Succeeded: Building Retry-Safe Mobile APIs
  • When Mobile Connections Break: Recovering Long-Running iOS Workflows With LangGraph and Event-Driven Backends
  • Performance Optimization Techniques in Flutter 3.41 for Mobile App Development

Trending

  • Delta Lake UniForm to Snowflake: Cross-Platform Table Access Without a Second Copy
  • Giving AI Agents Safe Access to Legacy Systems: Introducing legacy2mcp
  • Beyond the Endpoint: How Agent Cards Enable Discovery, Interoperability, and Trust
  • Google Cloud KMS vs. AWS KMS: Java Encryption Guide

Draft This article hasn't been published, so readers can't see it.

In moderation This article is waiting for review, so readers can't see it yet.

Deleted This article has been deleted, so readers can't see it.

SSL Certificate Pinning on iOS Using TrustKit

With the proliferation of mobile and wearable tech, the security of these devices has never been more important. Learn how to better secure your iOS code.

By 
Dmitry Fink
·
Jul. 26, 17 · Tutorial
Post on X (opens in a new tab) Share on LinkedIn (opens in a new tab)
8.8K Views

Join the DZone community Save articles, join the discussion, and download Refcards and Trend Reports with a free account.

Join for free Already a member? Log in

In past posts, I covered why certificate pinning in mobile apps is important and illustrated how to implement it both in iOS and Android. For the sake of simplicity, we had to omit a lot of nasty details and corner cases from our example. In the real world, the code might get complex very quickly, when you have to support various legacy iOS platforms, various popular networking libraries out there, etc. Luckily, the nice folks at DataTheorem have created and open-sourced a framework for SSL pinning that simplifies most of this process. The framework, called TrustKit, makes it very easy to integrate pinning into your mobile application. In the following tutorial, we’ll show you how to use it on iOS.

Installing the Framework

It is trivial to install the TrustKit framework using CocoaPods.

Just run the following to your Podfile:

pod 'TrustKit'

and run:

pod install

Alternatively, TrustKit is available through Carthage as well.

Add the following line to your Cartfile:

github "datatheorem/TrustKit"

and run:

carthage build --platform iOS

Preparing the Pins

As we explained in our introduction tutorial, you can pin either the certificate itself or the public key from within the certificate. The latter is preferred, since on many occasions, for security reasons, the certificates are being rotated regularly and we will have to redeploy our application with the new certificate, with a risk of some users getting locked out. We’ve also shown that it is better for the app to store just the hash of the public key, not the key itself. TrustKit takes the same approach. For each domain, it expects to have a list of hashes of public keys to pin. It does, however, expect them in a base64 encoded format, so, for reasons of convenience, a special tool is provided within the TrustKit package to help prepare them.

As with the previous example, we will use www.google.com as an example. Let's first extract the certificate from the domain:

openssl s_client -connect www.google.com:443 -showcerts < /dev/null | openssl x509 -outform DER > google.der

Now, let's run the provided helper script to extract the hash of the public key:


python get_pin_from_certificate.py --type DER ../google.der

In our example, we are using a binary DER format when working with certificates. You have your certificate provided to you in a different text PEM format. In that case, simply omit the –type DER part and call the script on your PEM file directly.

The result is going to be the following:

CERTIFICATE INFO
----------------
subject= /C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
issuer= /C=US/O=Google Inc/CN=Google Internet Authority G2
SHA1 Fingerprint=FB:BD:7E:87:A8:A6:EB:FC:3E:E0:BE:F8:2E:3A:EB:9C:7D:86:7F:AA
 
TRUSTKIT CONFIGURATION
----------------------
kTSKPublicKeyHashes: @[@"U9GGUC1+PGI7SLb8XVVuuBPLkQKbQ2LnfU5Wfe7WAAg="] // You will also need to configure a backup pin
kTSKPublicKeyAlgorithms: @[kTSKAlgorithmRsa2048]

Note that the output of the script has both the hash and the algorithm used. This is, in fact, a nice touch. TrustKit supports several algorithms and will auto-detect and handle it automatically for us. Notice the output of that script is even giving us Objective-C elements so we can copy-paste them into our code directly. Unfortunately, we will be using Swift for our example, but TrustKit gets extra points for this.

Initializing TrustKit

Now it's time to initialize the framework:

        let trustKitConfig = [
            kTSKSwizzleNetworkDelegates: false,
            kTSKPinnedDomains: [
                "google.com": [
                    kTSKIncludeSubdomains : true,
                    kTSKPublicKeyAlgorithms: [kTSKAlgorithmRsa2048],
                    kTSKPublicKeyHashes: [
                        "U9GGUC1+PGI7SLb8XVVuuBPLkQKbQ2LnfU5Wfe7WAAg=",
                        "WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="
                    ],]]] as [String : Any]
        TrustKit.initialize(withConfiguration: trustKitConfig)

The pinned domains is an array, so we can actually pin several different domains in our application, each with a specific set of hashes and settings.

Why do we have 2 hashes in the hashes list? TrustKit will actually fail and not let you start with one. The idea is you have to create a backup key, so in case your primary gets compromised, you will have a way to replace the certificates on your server without locking out your users.

Validating Secure Connections

Now that everything is set up, we are ready to use the TrustKit mechanism to actually validate each and every connection our application is going to open. In order to do this, we will make sure our URLSession delegate implements the didReceive challenge method:

    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {
        // Let TrustKit handle it
        TSKPinningValidator.handle(challenge, completionHandler: completionHandler)
    }

That's it, we're done! Every time our URLSession will try to establish an SSL connection to google.com or one of its subdomains, TrustKit will make sure to extract the certificate and the public key, hash the key and compare it to the list we’ve passed during initialization. And it will work on all iOS/watchOS/tvOS, and macOS versions.

mobile app

Published at DZone with permission of Dmitry Fink. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • The 30 Seconds Before a Mobile App Crash: The Evidence Most Systems Never Capture
  • The Request Timed Out, But the Payment Succeeded: Building Retry-Safe Mobile APIs
  • When Mobile Connections Break: Recovering Long-Running iOS Workflows With LangGraph and Event-Driven Backends
  • Performance Optimization Techniques in Flutter 3.41 for Mobile App Development

Partner Resources

×

Comments

Loading comments

The comments didn't load

Please try again in a moment.

Likes

Loading

The next likes didn't load. Please try again.

The likes didn't load

Please try again in a moment.

See who liked this

Log in or join DZone for free to see who liked this article.

Log in Join for free
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook