Qburst Logo
Industries
Solutions
Services
Innovation & Insights
Company
Industries
Solutions
Services
Innovation & Insights
Company
Public Key Info Hash SSL Pinning in Swift Using TrustKit
  1. Innovation & Insights
  2. Blog
|
GeneralMobile

Public Key Info Hash SSL Pinning in Swift Using TrustKit

Anna Thomas
Anna Thomas

Latest Posts

  • Connecting the Factory Floor to the Cloud for Real-Time Manufacturing Insights

  • How Our Self-Service AI Layer for CheckoAutomates Infrastructure Security

  • Re-Engineering Facilities Management with Dynamics 365

  • AI Can Generate Screens, But Who Designs Experiences?

  • What Spreadsheets Taught me About the Future of Agentic AI

This post is for anyone who’s trying to implement Public Key Info Hash SSL Pinning in iOS using TrustKit. The process is very straightforward except when you goof up by missing a tiny detail. A lot of documentation is already available on this topic. I’m just bringing the whole process under one roof.

What Is SSL Pinning? 

SSL pinning is a mechanism that is used to enhance app security. It helps mitigate man-in-the-middle attacks by validating the certificate or the public key pin of the host. We “pin” the host using its certificate or public key. All requests that are not associated with the certificate (or the public key) are rejected.   

There are two major types of pinning—Certificate Pinning and Public Key Pinning. Certificate Pinning is more easily done but requires the app to be updated once the certificate expires. Alamofire Library for iPhone supports Certificate Pinning. Public Key Pinning, on the other hand, has more varieties and allows more flexibility but is trickier to implement due to the extra steps required to extract the public key information from the certificate itself. 

Here we’ll look at how to pin the base64-encoded SHA-256 of a certificate’s Subject Public Key Info using TrustKit. We’ll go through the installation process in detail. Towards the end of the post, I’ve provided details of the tool that you can use to verify if the pinning is set correctly for your app. 

Let’s Get Started…

The first step is very simple. Integrate TrustKit in your project. The recommended method is through CocoaPods.

Add the following line to your Podfile:

pod 'TrustKit'

Then run the following command:

$ pod install

Now that we have the library in place, let’s follow the TrustKit documentation to enable SSL Pinning for our project.

Create a new Swift file. I’m going to call mine Security.swift. This is where we store all the security-related code. 

Import TrustKit and add the TrustKit code to this file. The file would look something like this:

1import Foundation
2import TrustKit
3
4class Security: NSObject {
5    static let publickKeyHash = "your public key hash here"
6    static let backupPublickKeyHash = "your backup public key hash here"
7    
8    class func startSSLPinning() {
9        let trustKitConfig = [
10            kTSKSwizzleNetworkDelegates: false,
11            kTSKPinnedDomains: [
12                "yourDomainName.com": [
13                    kTSKIncludeSubdomains: true,
14                    kTSKEnforcePinning: true,
15                    kTSKPublicKeyHashes: [
16                        publickKeyHash,
17                        backupPublickKeyHash
18                    ],]]] as [String : Any]
19
20        TrustKit.initSharedInstance(withConfiguration:trustKitConfig)
21    }
22}
23

You might have noticed the placeholder values — these are items that you’ll need to fill in. How? Pretty simple.

yourDomainName.com should have the domain that you’re trying to pin (for example, apple.com). Set the key kTSKIncludeSubdomains to true to ensure that all subdomains are also pinned (for example, developer.apple.com).

Now, to get the public key hash, you have two methods: the long one and the short one. You can use the short method to quickly find the keys to be added. Go for the long method to verify the keys that you’ve added, just for your satisfaction.

The Short Method

Go to SSL Labs and enter the domain name (for example, apple.com) and click Submit. You’ll see a lot of certificates and their related info.

That highlighted bit of info stated as “Pin SHA256” is what you want. It ends with a “=” symbol. This is what you’ll need to paste in your Security.swift file in the place of your public key hash here.

If you search on the page, you’ll find a lot of public key hashes.

All the SHA256 values

So which one to use? This is where you use the long method.

The Long Method

For this, you’ll require the certificate of the domain. It’s a .crt file that you have to obtain from the client or the domain owner. We’ll generate the public key hash using this .crt file and verify it on SSL Labs website.

Once you have the .crt file, download it into a folder. In the command line, go to the folder where the file is downloaded and paste the following:

openssl x509 -in my-certificate.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

Replace my-certificate.crt with the file name that you’ve downloaded. Press Enter and you’ll be able to see the public key hash with the “=” at the end. Copy the key and verify it by searching for that string on SSLLabs site.

For TrustKit, you need to provide two keys in the code, so you’ll need one more Public Key hash, preferably of the root certificate. This can be obtained from SSLLabs or if the client has provided the .crt file, you can generate the key using the above method.

Now that you have the hash key values, paste them in the Security.swift file. Now to enable pinning, add the following line inside your appDelegate’s didFinishLaunchingWithOptions method:

Security.startSSLPinning()

Now the pinning code is set. Now we need to add the pinning validator code. The Objective C code as per TrustKit documentation is given below.

You need to add the following bit of code inside the NSURLSessionDelegate method (URLSession:task:didReceiveChallenge:completionHandler:). This is the equivalent Swift code for the above.

1func urlSession(_ session: URLSession,
2                         task: URLSessionTask,
3                         didReceive challenge: URLAuthenticationChallenge,
4                         completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
5         // Call into TrustKit here to do pinning validation
6         if TrustKit.sharedInstance().pinningValidator.handle(challenge, completionHandler: completionHandler) == false {
7             // TrustKit did not handle this challenge: perhaps it was not for server trust
8             // or the domain was not pinned. Fall back to the default behavior
9             completionHandler(.performDefaultHandling, nil)
10         }
11     }
12

This seems pretty simple enough, but if you, like me, have a Base API class, then chances are you might not be able to access this particular delegate method. If you are able to access it, well and good. If not, you might need to implement a custom SessionDelegate class to access this delegate method.

IMPORTANT: The next step is required only if you’re not able to access the above delegate method in your base class where you are implementing the session handling.

So in my code, I had to create a custom SessionDelegate class so as to access this required session delegate method:

1class CustomSessionDelegate: SessionDelegate {
2
3    override func urlSession(_ session: URLSession,
4                         task: URLSessionTask,
5                         didReceive challenge: URLAuthenticationChallenge,
6                         completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
7         // Call into TrustKit here to do pinning validation
8         if TrustKit.sharedInstance().pinningValidator.handle(challenge, completionHandler: completionHandler) == false {
9             // TrustKit did not handle this challenge: perhaps it was not for server trust
10             // or the domain was not pinned. Fall back to the default behavior
11             completionHandler(.performDefaultHandling, nil)
12         }
13     }
14}
15

This is how I created my session:

var session = Session(delegate:CustomSessionDelegate(), eventMonitors:[customEvenitMonitor()]

As you can see, my session is getting assigned the CustomSessionDelegate because the eventMonitor class DOES NOT have the above required delegate accessible from it. Hence for me, this particular session delegate method was not available to implement the TrustKit code (hence all this noise about Custom Session Delegate!). I’m sure for all other cases, you don’t need to implement this. But if you DO get stuck, this should help.

Alright ,  so our development is complete! Make sure that when an API call is fired, you get a call inside this SessionDelegate method (URLSession:task:didReceiveChallenge:completionHandler:) where we’ve implemented the TrustKit checking.

Testing SSL Pinning Using Burp Suite

Now that we’ve completed the development required for SSL Pinning, it’s time to test it. You can test your app using Burp Suite Mac (the instructions for that are here) and you’ll get a fool-proof SSL Pinned code ready to ship! 

 

Latest Posts

  • Connecting the Factory Floor to the Cloud for Real-Time Manufacturing Insights

  • How Our Self-Service AI Layer for CheckoAutomates Infrastructure Security

  • Re-Engineering Facilities Management with Dynamics 365

  • AI Can Generate Screens, But Who Designs Experiences?

  • What Spreadsheets Taught me About the Future of Agentic AI

Recognized for Growth. Trusted for Impact.

Deloitte Technology Fast 50 India, Winner 2024

Deloitte Fast 50 India, Winner 2024

Dun & Bradstreet

Leading Mid-Corporates of India, 2024

RecognitionImage

Major Contender, QE Specialist Services


Qburst Logo
ISO
QBurst on LinkedIn
QBurst on X
QBurst on Facebook
QBurst on Instagram
Industries
RetailRealtyHigh-TechHealthcareManufacturing
Solutions
Digital ExperienceIntelligent EnterpriseProduct EngineeringManaged AgentsModernization
Services
Experience DesignDigital EngineeringDigital PlatformsData Engineering & AnalyticsApplied AICloudQuality EngineeringGlobal Capability CentersDigital Marketing
Innovation & Insights
BlogCase StudiesWhitepapersBrochures
Company
LeadershipClientsPartnersCorporate ResponsibilityNews & MediaCareersOur LocationsGrowth Referral
  • Industries
  • Solutions
  • Services
  • Innovation & Insights
  • Company

© QBurst 2026. All Rights Reserved.

Privacy Policy

Cookies & Management

Certifications