iPhone:HTTPS客户端证书身份验证

时间:2009-09-22 15:01:14

标签: iphone authentication ssl certificate

我正在与客户端证书身份验证进行斗争。当服务器需要凭证(在这种情况下是证书)时,将从 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 个答案:

答案 0 :(得分:4)

我使用以下步骤:

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

答案 1 :(得分: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;
}

答案 2 :(得分:0)

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