Preventing Man-in-the-Middle Attacks in iOS with SSL Pinning

In this tutorial, you’ll learn how to prevent man-in-the-middle attacks using SSL Pinning and Alamofire. You’ll use the Charles Proxy tool to simulate the man-in-the-middle attack. By Lorenzo Boaro.

Leave a rating/review
Download materials
Save for later

Nowadays, most iOS apps communicate with a server to retrieve information to work with. When apps exchange information, they typically use the Transport Layer Security (TLS) protocol to provide secure communications.

Apps don’t usually determine which certificates to trust and which not to trust when they try to establish a connection with a server. Rather, they rely entirely on the certificates that iOS contains.

Even if TLS protects the transmitted data against eavesdropping and tampering, attackers can set up man-in-the-middle attacks using hacked or self-signed certificates. Through these certificates, they can capture data moving to and from your app.

In this tutorial, you’ll learn how to prevent man-in-the-middle attacks using SSL Certificate Pinning and Alamofire 5. To verify that your implementation works as expected, you’ll use Charles Proxy‘s man-in-the-middle strategy.

Note: Secure Sockets Layer (SSL) is the ancestor of TLS. TLS addresses various security vulnerabilities identified by Internet Engineering Task Force (IETF) which affected SSL version 3.0. Throughout this tutorial, you should read SSL and TLS as synonyms, but code implementation should always use TLS.

Getting Started

For this tutorial, you’ll use PinMyCert, an iOS app that uses the Stack Exchange REST API to retrieve Stack Overflow users.

Start by downloading the starter project using the Download Materials button at the top or bottom of this tutorial. Once downloaded, open PinMyCert.xcodeproj in Xcode.

To keep you focused, the starter project has everything unrelated to SSL Certificate Pinning already set up for you.

Open Main.storyboard and look at the view controllers contained within. The view controller on the left is the root navigation controller of the app. Next, you have ViewController, which includes a table that lists the users retrieved from Stack Overflow. Finally, you have DetailViewController, which displays the detail for the selected user.

ViewController uses NetworkClient. This is a wrapper around Alamofire which exposes an API that performs network requests. In NetworkClient, you’ll implement the logic for dealing with SSL Certificate Pinning. More on that later.

Build and run the app, and you’ll see this initial screen:

Initial Screen

Before diving directly into the code, let’s talk about TLS!

Understanding TLS

Public key plus private key equals…

Off to the TLS lab!

To understand SSL Certificate Pinning, you should first grasp the essence of TLS and its cryptographic underpinnings.

The main goal of TLS is to add privacy and integrity to messages exchanged between two parties. In other words, TLS allows you to transmit data over a network without exposing that data to untrusted third parties.

When a client and a server need a TLS connection, building that connection follows three phases, executed in a specific order.

TLS Handshake

The Three Phases of TLS Connections

In the first phase, the client initiates a connection with the server.

The client then sends the server a message, which lists the versions of TLS it can support along with the cipher suite it can use for encryption.

Note: A cipher suite is a set of algorithms that you need to secure a network connection through TLS. For more info, please refer to cipher suite.

The server responds with the selected cipher suite and sends one or more digital certificates back to the client.

The client verifies that those digital certificates — certificates, for short — are valid. It also verifies that the server is authentic and not someone who wants to snoop sensitive information.

If the validation succeeds, the second phase of verification begins. The client generates a pre-master secret key and encrypts it with the server’s public key — i.e., the public key included in the certificate.

The server receives the encrypted pre-master secret key and decrypts it with its private key. The server and client each generate the master secret key and session keys based on the pre-master secret key.

Note: The second phase uses public-key cryptography or asymmetric cryptography. This is a cryptographic system that uses pairs of keys: Public keys, which are widely disseminated and private keys, which only the owner knows.

That master secret key is then used in the last phase to decrypt and encrypt the information that the two actors exchange.

Note: The third phase uses symmetric-key cryptography, where you use the same key for both encryption of plaintext and decryption of ciphertext.

About Digital Certificates

As you’ve learned in the previous section, the server sends one or more certificates back to the client.

So, what’s a certificate? A certificate is a file that encapsulates information about the server that owns the certificate. It’s similar to an identification card, such as a passport or a driver license.

A Certificate Authority (CA) can issue a certificate or it can be self-signed. In the first case, the CA must validate the identity of the certificate holder both before it issues the certificate and when your app uses the certificate. In the second case, the same entity whose identity it certifies signs the certificate.

The Structure of a Digital Certificates

The structure of a certificate uses X.509 standard. Here are the main fields:

  • Subject: Provides the name of the entity (computer, user, network device, etc.) that the CA issued the certificate to.
  • Serial Number: Provides a unique identifier for each certificate that a CA issues.
  • Issuer: Provides a unique name for the CA that issued the certificate.
  • Valid From: Provides the date and time when the certificate becomes valid.
  • Valid To: Provides the date and time when the certificate is no longer considered valid.
  • Public Key: Contains the public key of the key pair that goes with the certificate.
  • Algorithm Identifier: Indicates the algorithm used to sign the certificate.
  • Digital Signature: A bit string used to verify the authenticity of the certificate.

The couple consisting of the public key and the algorithm identifier represents the subject public key info.

X.509 Digital Certificate

X.509 certificates can be encoded differently, which will affect their appearance. The most common are: