SSL/Certificate pinning plays a very critical role in building highly secure mobile apps which users will be able to use even in countless insecure wireless network connections.
At a glance, Idea is the SSL(Secure Socket Layer) ensures the encrypted client-server communication over HTTPS. The encryption is based on PKI (Public Key Infrastructure) and a session key. The session key was introduced because encrypting and decrypting a public/private key uses a lot of processing time/power/space for sure it will slow down the process.
MIMT, Yes SSL Communication is very secure but the man-in-the-middle attack still poses an exact threat using ARP cache poisoning and DNS spoofing.
SSL/Certificate Pinning, ensure that the app communicates only with the designated server only and the prerequisites for SSL pinning is saving the target’s server SSL certificate within the app bundle.
SSL pinning is implemented within the
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
and here are the steps we need to follow.
- First read the server trust and server certificate.
let serverTrust = challenge.protectionSpace.serverTrust
let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0)
- Now set the policies for server validation, previous failure count etc.
SecTrustSetPolicies(serverTrust, SecPolicyCreateSSL(true, (challenge.protectionSpace.host as CFString)))
- Start policies validation, convert server certificate in Data and get the local certificate from bundle.
let remoteCertificateData = SecCertificateCopyData(certificate)
let pathToCert = Bundle.main.path(forResource: “certificate”, ofType: “cer”)
At last compare your policies result and local certificate data with your server certificate data, if everything goes well complete the challange with credentail.
Otherwise cancel the authentication and pass nil as credentails.