2017-02-09 208 views
1

我試圖實現相互TLS連接。這裏是流量:使用客戶端證書和secp512r1失敗的TLS 1.2連接

  • 我生成CSR請求(使用橢圓曲線密鑰,secp512r1)
  • 發送簽名請求到服務器並接收的公鑰證書作爲響應
  • 我讓P12證書使用步驟2中收到的公鑰證書和我的ECC secp512r1私鑰。我把它保存爲文檔「ca.p12」文件
  • ,當我得到NSURLAuthenticationMethodClientCertificate挑戰我使用的憑據從此證書
  • 獲取Error Domain=NSURLErrorDomain Code=-1200「發生SSL錯誤,無法進行到服務器的安全連接解決它「。

雖然檢查服務器和客戶端之間的流量似乎是客戶端問題。

問題

  1. 確實iOS的9/10支持橢圓曲線按鍵,secp512r1在TLS握手?
  2. 我錯過了什麼?

任何想法,建議真的很感激。謝謝。

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

根據PKIX(網絡的PKI),在鏈應該(必須?)的所有證書使用'secp512r1'。另外,服務器必須支持'secp512r1'。要查看'secp512r1'是否是問題,請使用'secp256k1'測試。它是最常見的曲線,並提供了該領域最多的互操作性。 – jww

+0

@jww不幸的是,我不能使用secp256進行測試,因爲服務器只支持secp512r –

+1

嗯,問題是Apple的SecureTransport可能是越野車。蘋果以其軟件質量差而聞名(參見[goto fail](https://nakedsecurity.sophos.com/2014/02/24/anatomy-of-a-goto-fail-apples-ssl-bug)解釋/非正式補丁/),[SSL_OP_SAFARI_ECDHE_ECDSA_BUG](https://wiki.openssl.org/index.php/SSL_OP_SAFARI_ECDHE_ECDSA_BUG)等)。我認爲你需要隔離secp512r1曲線的客戶端證書來發現問題所在。使用secp256k1會測試客戶端證書。你能用'openssl s_client'或其他工具來測試客戶端證書嗎? – jww

回答

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)