具有客户端证书的SecTrustSetAnchorCertificates

时间:2013-03-10 19:31:46

标签: ios ssl x509 pki ca

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

- (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-cert加载到系统密钥环中时,一切正常,甚至客户端证书也会发送到服务器,服务器可以识别用户。我的事

SecTrustSetAnchorCertificates(serverTrust, certArrayRef);

影响某种程度的信任,因为当我跳过这个电话时,我可以这样做:

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

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

我做错了什么?

非常感谢, 亚当

1 个答案:

答案 0 :(得分:2)

看一下这段代码

https://github.com/dirkx/Security-Pinning-by-CA

通过相当小心地保持两个信任块分开(你似乎正在混合)来做到这两点。