#はじめに
iOSアプリケーションの安全性を上げるために、MITM対策をCertificate Pinningをやってみました。
MITMやSSLとは?という方は下記のWikipediaを参考にしてください。
MITM SSL/TLS
#環境
・Xcode 9.3
・Swift 4.1
・macOS 10.3
#実装
通信を行うクラスにURLSessionDelegateを継承してください。
継承したクラスに下記のurlSessionメソッドを追加してください。
func urlSession(_ session: URLSession, didReceive challenge:URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
let serverTrust = challenge.protectionSpace.serverTrust
let certificate = SecTrustGetCertificateAtIndex(serverTrust!, 0)
//ドメイン名を確認するpoliciesにSSLをセットする
let policies = NSMutableArray()
policies.add(SecPolicyCreateSSL(true, (challenge.protectionSpace.host as CFString)))
SecTrustSetPolicies(serverTrust!, policies)
//SSL証明書をチェックする
var result: SecTrustResultType = SecTrustResultType(rawValue: 0)!
SecTrustEvaluate(serverTrust!, &result)
let isServerTrusted:Bool = result == SecTrustResultType.unspecified || result == SecTrustResultType.proceed
//ローカルとリモートの証明書データを取得する
let remoteCertificateData:NSData = SecCertificateCopyData(certificate!)
//○○○に証明書ファイル名、□□□に型名を入れる
let pathToCert = Bundle.main.path(forResource: "○○○", ofType: "□□□")
let localCertificate:NSData = NSData(contentsOfFile: pathToCert!)!
if (isServerTrusted && remoteCertificateData.isEqual(to: localCertificate as Data)) {
let credential:URLCredential = URLCredential(trust: serverTrust!)
completionHandler(.useCredential, credential)
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
これで基本的な実装は終了です。
後はこのようにすれば完成です。
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration, delegate: self, delegateQueue:OperationQueue.main)
var request = URLRequest(url:url)
let task = session.dataTask(with: request) { data, response, error in
//処理を書く
}
実行確認はこちら等を参考に
Charlesで他社アプリの通信を覗く