iPhone:HTTPS客户端证书验证

21

我正在处理客户端证书认证问题。当服务器需要凭据时(在这种情况下是证书),NSURLConnection代理会调用此方法:

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

我想从文件中加载一个证书,填写凭据并运行此方法:
[[challenge sender] useCredential:[self credential] forAuthenticationChallenge:challenge];

但我不知道如何初始化(或填充)SecIdentityRef参数。这是创建凭证的代码:

NSString *certPath = [[NSBundle mainBundle] pathForResource:@"certificate" ofType:@"cer"];
NSData *certData = [[NSData alloc] initWithContentsOfFile:certPath];

SecIdentityRef myIdentity;  // ???

SecCertificateRef myCert = SecCertificateCreateWithData(NULL, (CFDataRef)certData);
[certData release];
SecCertificateRef certArray[1] = { myCert };
CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL);
CFRelease(myCert);
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity
                                  certificates:(NSArray *)myCerts
                                   persistence:NSURLCredentialPersistencePermanent];
CFRelease(myCerts);

有人知道如何解决吗?谢谢。


我终于找到了解决方案,但现在出现了一个新问题:

我的客户端没有向服务器发送证书。在服务器要求证书后,应用程序运行了这个方法:

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

我填写了凭据(就像我上面提到的),但连接以错误 NSURLErrorDomain -1206 结束。根据服务器日志,应用程序未发送客户端证书。

有人对此有经验吗?我需要在应用程序中验证证书吗?还是需要其他方面的操作才能使其正常工作?如果需要,我可以提供我的当前代码。感谢任何想法...

3个回答

4
我使用以下步骤:
  1. 使用SecPKCS12Import函数从pkcs12证书文件中提取SecIdentityRef
  2. 使用SecIdentityCopyCertificate函数获取SecCertificateRef
其余部分(凭据初始化)与我的问题中的相同...如果您愿意,我可以在这里放更多的代码。请注意,iPhone模拟器存在错误(http://openradar.appspot.com/7090030),因此无法在模拟器中使用大量证书。

1

如果您将此信息存储在钥匙串中,还可以在钥匙串中搜索身份验证:

+ (SecIdentityRef)dumpSecIdentityRef
{
OSStatus    err;
CFArrayRef  result;
CFIndex     resultCount;
CFIndex     resultIndex;

result = NULL;
err = SecItemCopyMatching((__bridge CFDictionaryRef) [NSDictionary dictionaryWithObjectsAndKeys:
                                                      (__bridge id)kSecClassIdentity,
                                                      kSecClass, kSecMatchLimitAll,
                                                      kSecMatchLimit, kCFBooleanTrue,
                                                      kSecReturnRef, kCFBooleanTrue,
                                                      kSecReturnAttributes, nil],
                          (CFTypeRef *) &result);

if ((result != NULL) && (err == noErr)) {

    NSMutableArray *identitiesArray = [NSMutableArray new];

    resultCount = CFArrayGetCount(result);
    for (resultIndex = 0; resultIndex < resultCount; resultIndex++) {
        NSDictionary *  thisResult;
        thisResult = (__bridge NSDictionary *) CFArrayGetValueAtIndex(result, resultIndex);
        NSLog(@"%@", (__bridge id)(result));
        [identitiesArray addObject:thisResult];
    }

    CFRelease(result);
    //TO DO - choose correct identity object from array.
    SecIdentityRef myIdentity = (__bridge SecIdentityRef)([[identitiesArray objectAtIndex:0] valueForKey:@"v_Ref"]);

    return myIdentity;
}
return nil;
}

0

当然,问题出在xcode中的iPhone模拟器上 :) 更新到3.1版本后,它开始工作了...


3
提高问题可读性的建议:不要将问题发布为新回答。这会使线程更难以阅读。请记住,你的问题可能对其他人有用,因此他们能够看到你的过程和最终答案非常重要。谢谢! - mtmurdock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接