2017-02-09 8 views
1

私は相互TLS接続を実装しようとしています。ここで流れは次のとおりです。クライアント証明書とsecp512r1を使用したTLS 1.2接続が失敗します

  • 私は(楕円曲線キーを使用して、secp512r1)CSR要求を生成
  • 私はP12証明書を作成し、サーバーへの署名要求を送信し、応答
  • として、公開鍵証明書を受け取ります手順2で受信した公開鍵証明書をECC secp512r1秘密鍵で使用します。私はError Domain=NSURLErrorDomain Code=-1200は、「SSLエラーが発生した取得とサーバーへの安全な接続を行うことができない私はNSURLAuthenticationMethodClientCertificate挑戦を得るとき、私は
  • この証明書の資格情報を使用して、それを解決
  • 文書で「ca.p12」ファイルとして保存します"

サーバーとクライアントの間のトラフィックを確認している間に、クライアント側の問題と思われます。

質問

  1. は、iOS 9/10サポート楕円曲線キー、TLSハンドシェイクでsecp512r1していますか?
  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

でそれを渡して、チェーン内のすべての証明書は、(必須?) 'secp512r1'を使用する必要があります。さらに、サーバは 'secp512r1'をサポートしなければなりません。 'secp512r1'が問題であるかどうかを調べるには、' secp256k1'でテストしてください。最も一般的な曲線であり、この分野で最も相互運用性があります。 – jww

+0

@jwwサーバーはsecp512rしかサポートしていないので、残念ながら私はsecp256でテストできません –

+1

問題は、AppleのSecureTransportがバグかもしれないということです。 Appleは、ソフトウェアの品質が悪いことでよく知られています(cf. [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

サーバーが証明書チェーン(クライアント証明書1つと中間証明書1つ)で自分の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]; 

は、次にPKIX(ウェブのPKI)によるとurlSession:didReceiveChallenge:completionHandler:

completionHandler(.useCredential, urlCredential) 
関連する問題