2

Hi guys Im trying to apply this authentication strategy . Basically I create RSA Key pair, then I create CSR(Certificate Signing Request), then I send it to server which will return (X.509)Self-signed client certificate in response. Then I remove ----BEGIN CERTIFICATE---- and ----END CERTIFICATE----, transform it to base64 encoded data with line length 64 characters, and save it to keychain this way

  1. create reference with let certRef: CFTypeRef? = SecCertificateCreateWithData(nil , cert)
  2. save it to keychain with let params: NSDictionary = [kSecClass as String: kSecClassCertificate, kSecValueRef as String: certRef!] let status = SecItemAdd(params, nil)

certificate is saved, now If I understand it correctly, if I have private key with which CSR was created saved in keychain, I should be able to get SecIdentity which I will use in NSURLSession to make request. So I created method to get this identity this is how it looks like :

     func getIdentityReference() -> SecIdentityRef? {
        let parameters = [
            kSecClass as String: kSecClassIdentity,
            kSecAttrApplicationTag as String: kAsymmetricCryptoManagerApplicationTag,
            kSecReturnRef as String: true
        ]
        var ref: AnyObject?
        let status = SecItemCopyMatching(parameters, &ref)
        if status == errSecSuccess { return ref as! SecIdentityRef? } else { return nil }
    } 

everything works fine, Im getting identity so the only thing to do is actual request. For that I need to implement NSURLSessionDelegate's did receive challenge method and here it is

func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
        let method = challenge.protectionSpace.authenticationMethod
        print(method)

        if method == NSURLAuthenticationMethodServerTrust {
            let host = challenge.protectionSpace.host
            print(host)

            let credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
            completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, credential)
        }

        let identity = AsymmetricCryptoManager.sharedInstance.getIdentityReference()!

        var certificate: SecCertificateRef? = nil
        SecIdentityCopyCertificate(identity, &certificate)

        var certArray = [certificate!]
        let credential = NSURLCredential(identity: identity, certificates: certArray, persistence: .Permanent)

        completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, credential)
    }

(I'm just prototyping, that's the reason for implicit unwrapping)

but when I fire this request I'm getting error

Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={_kCFStreamErrorCodeKey=-9824, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSUnderlyingError=0x13cfe7850 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9824, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9824}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://blabla.blabla, NSErrorFailingURLStringKey=https://blabla.blabla, _kCFStreamErrorDomainKey=3}

now I really don't know where is the problem, note that on Android everything works well, so server is set up correctly. Any help will be appreciated and it might help few people in the future. Thank you

beretis
  • 899
  • 1
  • 9
  • 24
  • I would suggest you check this [link](http://stackoverflow.com/questions/34223291/ios-certificate-pinning-with-swift-and-nsurlsession). – Dhruv Sep 29 '16 at 07:41

0 Answers0