証明書のピン留めをSwiftのNSURLSessionに追加する方法
OWASP Webサイト には、Objective-CおよびNSURLConnectionの例のみが含まれています。
準備が整いましたが、SecTrustEvaluate
は非推奨であり、SecTrustEvaluateWithError
に置き換える必要があります。
だからこれ:
var secresult = SecTrustResultType.invalid
let status = SecTrustEvaluate(serverTrust, &secresult)
if errSecSuccess == status {
// Proceed with evaluation
switch result {
case .unspecified, .proceed: return true
default: return false
}
}
私が書いた理由// Proceed with evaluation
セクションは、secresult
を検証する必要があるためです。これは、証明書が実際に無効であることを示している可能性もあります。これを上書きし、発生した問題を例外として追加するオプションがあります。できれば、ユーザーに決定を求めた後です。
これである必要があります:
if SecTrustEvaluateWithError(server, nil) {
// Certificate is valid, proceed.
}
2番目のパラメーターはエラーをキャプチャしますが、詳細に関心がない場合は、nil
を渡すだけです。
これを試すことができます。
import Foundation
import Security
class NSURLSessionPinningDelegate: NSObject, URLSessionDelegate {
let certFileName = "name-of-cert-file"
let certFileType = "cer"
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {
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 certificateOne = NSData(bytes: data, length: size)
let filePath = Bundle.main.path(forResource: self.certFileName,
ofType: self.certFileType)
if let file = filePath {
if let certificateTwo = NSData(contentsOfFile: file) {
if certificateOne.isEqual(to: certificateTwo as Data) {
completionHandler(URLSession.AuthChallengeDisposition.useCredential,
URLCredential(trust:serverTrust))
return
}
}
}
}
}
}
}
// Pinning failed
completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
}
}
ソース: https://www.steveclarkapps.com/using-certificate-pinning-xcode/