Skip to content

Instantly share code, notes, and snippets.

@29satnam
Created September 9, 2017 10:18
Show Gist options
  • Save 29satnam/a47d9b569204df7fcec4160027a4a0b8 to your computer and use it in GitHub Desktop.
Save 29satnam/a47d9b569204df7fcec4160027a4a0b8 to your computer and use it in GitHub Desktop.
SSL Pinning Swift 3
// Step 1: class ViewController: ..... URLSessionDelegate, URLSessionTaskDelegate
// Step 2: Usage
if let url = NSURL(string: "https://example.com") {
let session = URLSession(
configuration: URLSessionConfiguration.ephemeral,
delegate: NSURLSessionPinningDelegate(),
delegateQueue: nil)
let task = session.dataTask(with: url as URL, completionHandler: { (data, response, error) -> Void in
if error != nil {
print("error: \(error!.localizedDescription): \(error!)")
} else if data != nil {
if let str = NSString(data: data!, encoding: String.Encoding.utf8.rawValue) {
print("Received data:\n\(str)")
}
else {
print("Unable to convert data to text")
}
}
})
task.resume()
}
else {
print("Unable to create NSURL")
}
//Step 3: Add following code to a Swift file
import .....
import Security
class NSURLSessionPinningDelegate: NSObject, URLSessionDelegate {
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {
// Adapted from OWASP https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#iOS
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
if let serverTrust = challenge.protectionSpace.serverTrust {
var secresult = SecTrustResultType.invalid
let status = SecTrustEvaluate(serverTrust, &secresult)
if(errSecSuccess == status) {
if let serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0) {
let serverCertificateData = SecCertificateCopyData(serverCertificate)
let data = CFDataGetBytePtr(serverCertificateData);
let size = CFDataGetLength(serverCertificateData);
let cert1 = NSData(bytes: data, length: size)
let file_der = Bundle.main.path(forResource: "example.com", ofType: "der")
if let file = file_der {
if let cert2 = NSData(contentsOfFile: file) {
if cert1.isEqual(to: cert2 as Data) {
completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust:serverTrust))
return
}
}
}
}
}
}
}
// Pinning failed
completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
}
}
// Step 4: Run following command in terminal
openssl s_client -connect example.com:443 -showcerts < /dev/null | openssl x509 -outform DER > example.com.der
// Step 5: drop output der file to your project
example.com.dir -> project
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment