2013-03-10 390 views
2

我正在开发iOS应用程序。我们拥有带自签名ca-cert的自定义证书颁发机构。证书颁发机构也为用户和https服务器颁发证书。我想创建iOS应用程序,它可以使用ca证书验证https服务器,并且还可以使用客户端证书与https服务器通信。我已经有了使用客户端证书与https服务器进行通信的代码,但我需要将ca证书导入系统密钥环。我想将ca证书硬编码到应用程序中。我的代码如下所示:SecTrustSetAnchorCertificates与客户端证书

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { 

    bool result=NO; 
    if ([protectionSpace authenticationMethod] == NSURLAuthenticationMethodServerTrust) { 
     result= YES; 
    } else if([protectionSpace authenticationMethod] ==  NSURLAuthenticationMethodClientCertificate) { 
     result = YES; 
    } 
    return result; 
} 

- (BOOL)shouldTrustProtectionSpace:(NSURLProtectionSpace *)protectionSpace { 
    CFDataRef certDataRef = (__bridge_retained CFDataRef)self.rootCertData; 
    SecCertificateRef cert = SecCertificateCreateWithData(NULL, certDataRef); 

    SecTrustRef serverTrust = protectionSpace.serverTrust; 

    CFArrayRef certArrayRef = CFArrayCreate(NULL, (void *)&cert, 1, NULL); 
    SecTrustSetAnchorCertificates(serverTrust, certArrayRef); 

    SecTrustResultType trustResult; 
    SecTrustEvaluate(serverTrust, &trustResult); 

    return trustResult == kSecTrustResultUnspecified; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 

    NSLog(@"Did receive auth challange %@",[challenge debugDescription]); 

    NSURLProtectionSpace *protectionSpace = [challenge protectionSpace]; 

    NSString *authMethod = [protectionSpace authenticationMethod]; 
    if(authMethod == NSURLAuthenticationMethodServerTrust) { 
     NSLog(@"Verifying The Trust"); 

     NSURLCredential* cred=[NSURLCredential credentialForTrust:[protectionSpace serverTrust]]; 
     if ([self shouldTrustProtectionSpace:challenge.protectionSpace]) { 
      [[challenge sender] useCredential:cred forAuthenticationChallenge:challenge]; 
      NSLog(@"OK"); 
     } else { 
      NSLog(@"FAILED"); 
      [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge]; 
     } 

    } 
    if(authMethod == NSURLAuthenticationMethodClientCertificate) { 
     NSLog(@"Trying Certificate"); 
     ..... 

一切都像魅力,直到服务器不需要客户端证书。在这个时刻,我会收到错误此服务器的证书无效,执行不会到达点

NSLog(@"Trying Certificate"); 

当我有.der CA证书加载到系统钥匙圈,一切正常,即使客户端证书被发送到服务器,服务器可以识别用户。我东西

SecTrustSetAnchorCertificates(serverTrust, certArrayRef); 

影响莫名其妙的信任,因为当我跳过这个电话,我可以简单地做:

[[challenge sender] useCredential:cred forAuthenticationChallenge:challenge]; 

没有任何错误,但我无法验证证书在这种情况下。

我在做什么错?

非常感谢, 亚当

回答