2017-02-09 8 views
1

상호 TLS 연결을 구현하려고합니다. 여기 흐름입니다 : 클라이언트 인증서 및 secp512r1을 사용하는 TLS 1.2 연결이 실패합니다.

  • 내가 CSR 요청을 생성 (타원 곡선 키를 사용하여이 secp512r1)
  • 은 서버에 서명 요청을 보내고 나는 P12 인증서하게
  • 응답으로 공개 키 인증서를받을 2 단계에서받은 공개 키 인증서를 내 ECC secp512r1 개인 키로 사용합니다. 나는 문서에서 "ca.p12"파일로 저장
  • 나는 NSURLAuthenticationMethodClientCertificate 도전은 내가 SSL 오류가 발생하여 서버에 보안 연결을 할 수 없습니다 "Error Domain=NSURLErrorDomain Code=-1200을 가져 인증서
  • 에서 자격 증명을 사용하여 해결 얻을 때 . "

서버와 클라이언트 간의 트래픽을 확인하는 동안 클라이언트 쪽 문제인 것처럼 보입니다.

질문 :

  1. 합니까 아이폰 OS 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

에 전달. 또한, 서버는'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 -explained-plus-anofficial-patch /), [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]; 

그런 다음 체인해야 (필수?)의 모든 인증서는`secp512r1`를 사용, PKIX (웹의 PKI)에 따르면 urlSession:didReceiveChallenge:completionHandler:

completionHandler(.useCredential, urlCredential)