使用客户端证书和secp512r1的TLS 1.2连接失败

时间:2017-02-09 16:18:59

标签: ios swift nsurlsession tls1.2 mutual-authentication

我试图实现相互TLS连接。这是流程:

  • 我生成csr请求(使用椭圆曲线键,secp512r1)
  • 将签名请求发送到服务器并接收公钥证书作为回复
  • 我使用我的ECC secp512r1私钥使用在步骤2中收到的公钥证书制作p12证书。我把它保存为" ca.p12"文档
  • 中的文件
  • 当我遇到NSURLAuthenticationMethodClientCertificate质询时,我使用此证书中的凭据解析它
  • 获取Error Domain=NSURLErrorDomain Code=-1200"发生SSL错误,无法与服务器建立安全连接。"

在检查服务器和客户端之间的流量时,它似乎是客户端问题。

问题

  1. iOS 9/10在TLS握手中是否支持椭圆曲线键,secp512r1?
  2. 我错过了什么关键吗?
  3. 任何想法,建议都非常感谢。感谢。

    public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {
    
    //server trust works fine
    if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
        if (self.shouldTrustProtectionSpace(space: challenge.protectionSpace)) {
            completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
        }
    }
    //This one causes the issue
    else if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate) {
        let identityAndTrust: IdentityAndTrust = self.extractIdentity()
    
        let urlCredential: URLCredential = URLCredential(
            identity: identityAndTrust.identityRef,
            certificates: identityAndTrust.certArray as? [AnyObject],
            persistence: URLCredential.Persistence.forSession)
            completionHandler(.useCredential, urlCredential)
        }
    }
    
    struct IdentityAndTrust {
        var identityRef: SecIdentity
        var trust: SecTrust
        var certArray: AnyObject
    }
    
    func extractIdentity() -> IdentityAndTrust {
        var identityAndTrust: IdentityAndTrust!
        var securityError: OSStatus = errSecSuccess
    
        var path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
        path = path + "/ca.p12"
        //let path: String = NSBundle.mainBundle().pathForResource("client", ofType: "p12")!
        let PKCS12Data = NSData(contentsOfFile:path)!
        let key: NSString = kSecImportExportPassphrase as NSString
        let options: NSDictionary = [key : "123"]
        //create variable for holding security information
        //var privateKeyRef: SecKeyRef? = nil
    
        var items: CFArray?
    
        securityError = SecPKCS12Import(PKCS12Data, options, &items)
    
        if securityError == errSecSuccess {
            let certItems: CFArray = items as CFArray!
            let certItemsArray: Array = certItems as Array
            let dict: AnyObject? = certItemsArray.first
            if let certEntry: Dictionary = dict as? Dictionary<String, AnyObject> {
    
                // grab the identity
                let identityPointer: AnyObject? = certEntry["identity"]
                let secIdentityRef: SecIdentity = identityPointer as! SecIdentity!
                print("\(identityPointer)  :::: \(secIdentityRef)")
                // grab the trust
                let trustPointer: AnyObject? = certEntry["trust"]
                let trustRef: SecTrust = trustPointer as! SecTrust
                print("\(trustPointer)  :::: \(trustRef)")
    
                // grab the certificate chain
                var certRef: SecCertificate?
                SecIdentityCopyCertificate(secIdentityRef, &certRef)
                let certArray: NSMutableArray = NSMutableArray()
    
                let reader = DmailReader.sharedReader
                let caCertString = reader.getCACert()
                let cerData = X509Utility.der(fromData: caCertString)
    
                let convertedData = cerData as! CFData
                let caCert = SecCertificateCreateWithData(nil, convertedData)
                certArray.add(certRef as SecCertificate!)
                certArray.add(caCert!)
    
                identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef, certArray:  certArray)
            }
        }
        return identityAndTrust
    }
    

1 个答案:

答案 0 :(得分:0)

服务器似乎使用证书链响应了我的csr请求:一个客户端证书和一个中间证书。我只解析了第一个并显然跳过了中间版。

 /*identity only contains client cert. Certificates is the array of intermediate certificates (in my case its 1, can be more)*/
 NSURLCredential *credential = [[NSURLCredential alloc]initWithIdentity:identity
                                                           certificates:certificates
                                                            persistence:NSURLCredentialPersistencePermanent];

然后将其传递到urlSession:didReceiveChallenge:completionHandler:

completionHandler(.useCredential, urlCredential)