3

以下代码是我使用以前帖子中有关 ios 客户端证书身份验证的代码。每个人都说这有效,但是为什么它对我有效?!?!

我不断收到以下错误:

connection didFailWithError: Error Domain=NSURLErrorDomain Code=-1206 "The server “www.mywebsite.com” requires a client certificate.

我在 stackoverflow 上关注了至少 4 篇关于同一主题的帖子,在其他类似网站上关注了 2 篇。他们都说同样的话,只是它不起作用。

我知道我的PKCS12文件有效,因为我将它通过电子邮件发送到我的 ipad,我将它安装在 ipad 钥匙串上,并且我能够使用 Safari 访问和授权证书身份。只是当我尝试NSURLConnection在 3rd 方应用程序中使用它时,它拒绝让我这样做。

欢迎任何建议,我觉得我已经用尽了我的选择。


    // Download PKCS12 Cert from my FTP server.

    NSString *stringURL = @"ftp://user:password@myipaddress/myclientId.p12";        
    NSString* webStringURL = [stringURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL  *url = [NSURL URLWithString:webStringURL];
    NSData *p12Data = [NSData dataWithContentsOfURL:url];


    if ( p12Data )
    {   
        CFDataRef inP12data = (__bridge CFDataRef)p12Data;

        SecIdentityRef myIdentity;
        SecTrustRef myTrust;
        OSStatus errMsg = NULL;

        // This is the same function that has been reposted in all the other posts about ios client certification authentication.  So i'm not going to repost that.
        errMsg = extractIdentityAndTrust(inP12data, &myIdentity, &myTrust);

        SecCertificateRef myCertificate;
        SecIdentityCopyCertificate(myIdentity, &myCertificate);

        const void *certs[] = { myCertificate };

        CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);

        NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistenceNone];

        [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
4

2 回答 2

2

错误出现在这条线上。第二个参数需要设置为“nil”

    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistenceNone];

变成:

    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:nil persistence:NSURLCredentialPersistenceNone];
于 2013-05-07T22:34:23.000 回答
1

您的 .p12 可能包含中间证书,而您的服务器需要这些中间证书。

您可以使用 wireshark 验证您的代码将发送重复的身份证书,但在客户端证书响应中没有中间证书。

如果存在这种情况,您还需要从 p12 中提取证书并传递以创建 NSURLCredentials:

int count = SecTrustGetCertificateCount(myTrust);
NSMutableArray* myCertificates = nil;
if (count > 1) {
    myCertificates = [NSMutableArray arrayWithCapacity:SecTrustGetCertificateCount(myTrust)];
    for (int i = 1; i < count; ++i) {  // remove the leaf cert
         [certs addObject:(id)SecTrustGetCertificateAtIndex(myTrust, i)];
    }
}
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:myCertificates persistence:NSURLCredentialPersistenceNone];

此外,将 nil 传递给 NSURLCredential 不应破坏任何代码。请参阅 Apple 的示例: https ://developer.apple.com/library/ios/documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html 。但是将空数组 @[] 传递给 NSURLCredential 会崩溃。

于 2013-12-18T09:31:40.930 回答