iOS SSL pinning
SSL stands for Secure Socket Layer, which is a protocol for creating an encrypted connection between client and server. It ensures that all data pass in network will be private and integral.
How SSL works? When client establishes the connection with server (called SSL handshake):
- Client connects to server and requests server identify itself.
- Server sends certificate to client (include public key)
- Client checks if that certificate is valid. If it is, client creates a symmetric key (session key), encrypts with public key, then sends back to server
- Server receives encrypted symmetric key, decrypts by its private key, then sends acknowledge packet to client
- Client receives ACK and starts the session
Using SSL, the client will allow the connection only from trusted sources that have the valid certificate. And it looks good for most cases. But what if someone stands between client and server, and acts like they are the real server? Let's call client is C, server is S and the attacker is A.
In step 1, instead of sending packet to S, A can catch the packet and pretend it as S. What if instead of receiving certificate from S, client C will receive fake certificate from A and believe it's valid. A can make C think that it is communicating with S, but actually all connection flows will be directed to attacker A.
Hence, SSL pinning can be the solution to prevent Man-In-The-Middle (MITM) attack. SSL pinning will ensure that client connect with designated server. The main key of SSL pinning that server certificate will be saved in app bundle. Then, when client receives certificate from server, it then compares 2 certificates to make sure that they are the same before establishing the connection.
Now, I will show how to implement SSL pinning in iOS.
1. NSURLSession
For NSURLSession, the main method to handle SSL pinning is URLSession:didReceiveChallenge:completionHandler:delegate. Set your class to conform URLSessionDelegate and paste this function to your class:
This function will “requests credentials from the delegate in response to an authentication request from the remote server.” We will compare the certificate from server with the one that saved in app bundle. If 2 certificates are identical, the authentication will let it pass and client can connect to server.
2. Alamofire
Alamofire may be the most popular library for HTTP networking in Swift. It has the built-in function for SSL pinning and very easy to use.
One disadvantage of SSL pinning is that you have to save the certificate in the app. Whenever the certificate is updated, we need to release new version of app. But this also leads to another problem: what we do with older version?
- Maintain the old certificate for a time, until we make sure all users have downloaded new version already.
- A special flow to download new certificate. But what if this flow is attacked?