web-dev-qa-db-fra.com

Épinglage de certificat iOS avec Swift et NSURLSession

Comment ajouter l'épinglage de certificat à une session NSURL dans Swift?

Le site Web OWASP ne contient qu'un exemple pour Objective-C et NSURLConnection.

12
lifeisfoo

Attention, SecTrustEvaluate est obsolète et devrait être remplacé par SecTrustEvaluateWithError.

Donc ça:

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
   }
}

La raison pour laquelle j'ai écrit le // Proceed with evaluation est parce que vous devez valider le secresult et cela pourrait impliquer que le certificat n'est pas valide. Vous avez la possibilité de remplacer cela et d'ajouter tous les problèmes soulevés en tant qu'exceptions, de préférence après avoir invité l'utilisateur à prendre une décision.

Devrait être ceci:

if SecTrustEvaluateWithError(server, nil) {
   // Certificate is valid, proceed.
}

Le deuxième paramètre capturera toute erreur, mais si vous n'êtes pas intéressé par les détails, vous pouvez simplement passer nil.

1
thecivillain

Vous pouvez essayer ça.

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)
}
}

Source: https://www.steveclarkapps.com/using-certificate-pinning-xcode/

0
Sour LeangChhean