菜鸟教程小白 发表于 2022-12-11 18:53:51

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


                                            <p><p>我正在尝试实现双向 TLS 连接。这是流程:</p>

<ul>
<li>我生成 csr 请求(使用椭圆曲线 key ,secp512r1)</li>
<li>向服务器发送签名请求并接收公钥证书作为响应</li>
<li>我使用在步骤 2 中收到的公钥证书和我的 ECC secp512r1 私钥制作 p12 证书。我将它保存为 Documents 中的“ca.p12”文件</li>
<li>当我收到 <code>NSURLAuthenticationMethodClientCertificate</code> 挑战时,我会使用此证书中的凭据解决它</li>
<li>Get <code>Error Domain=NSURLErrorDomain Code=-1200</code> "发生 SSL 错误,无法与服务器建立安全连接。"</li>
</ul>

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

<p><strong><em>问题</em></strong>:</p>

<ol>
<li>iOS 9/10 是否支持 TLS 握手中的椭圆曲线键 secp512r1? </li>
<li>我错过了什么重要的事情吗?</li>
</ol>

<p>任何想法,建议都非常感谢。谢谢。</p>

<pre><code>public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -&gt; 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? ,
      persistence: URLCredential.Persistence.forSession)
      completionHandler(.useCredential, urlCredential)
    }
}

struct IdentityAndTrust {
    var identityRef: SecIdentity
    var trust: SecTrust
    var certArray: AnyObject
}

func extractIdentity() -&gt; IdentityAndTrust {
    var identityAndTrust: IdentityAndTrust!
    var securityError: OSStatus = errSecSuccess

    var path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as String
    path = path + &#34;/ca.p12&#34;
    //let path: String = NSBundle.mainBundle().pathForResource(&#34;client&#34;, ofType: &#34;p12&#34;)!
    let PKCS12Data = NSData(contentsOfFile:path)!
    let key: NSString = kSecImportExportPassphrase as NSString
    let options: NSDictionary =
    //create variable for holding security information
    //var privateKeyRef: SecKeyRef? = nil

    var items: CFArray?

    securityError = SecPKCS12Import(PKCS12Data, options, &amp;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&lt;String, AnyObject&gt; {

            // grab the identity
            let identityPointer: AnyObject? = certEntry[&#34;identity&#34;]
            let secIdentityRef: SecIdentity = identityPointer as! SecIdentity!
            print(&#34;\(identityPointer):::: \(secIdentityRef)&#34;)
            // grab the trust
            let trustPointer: AnyObject? = certEntry[&#34;trust&#34;]
            let trustRef: SecTrust = trustPointer as! SecTrust
            print(&#34;\(trustPointer):::: \(trustRef)&#34;)

            // grab the certificate chain
            var certRef: SecCertificate?
            SecIdentityCopyCertificate(secIdentityRef, &amp;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
}
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>服务器似乎使用证书链响应了我的 csr 请求:一个客户端证书和一个中间证书。我只解析了第一个,显然跳过了中间。</p>

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

<p>然后传入 <code>urlSession:didReceiveChallenge:completionHandler:</code></p>

<pre><code>completionHandler(.useCredential, urlCredential)
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 使用客户端证书和 secp512r1 的 TLS 1.2 连接失败,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/42141722/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/42141722/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 使用客户端证书和 secp512r1 的 TLS 1.2 连接失败