gpt4 book ai didi

iOS - 以编程方式信任 CA(证书颁发机构)

转载 作者:可可西里 更新时间:2023-11-01 05:40:59 24 4
gpt4 key购买 nike

我正在尝试使用一个应用程序来通过套接字/流从 iPhone 客户端安全地连接到 TLS 服务器以进行一般数据交换。为此,我使用 mac keychain-tool 设置了自己的 CA,并将证书包含在代码包中。

现在我的应用程序应该信任该 CA 颁发的任何服务器证书。 (我不关心其他应用程序如何处理这些证书,我认为他们不会因为沙盒而信任它。)

我在网上发现了几个类似的问题,但似乎有问题。

如果我将 CA 证书拖放到模拟器中并手动接受以信任它,则与服务器的连接似乎工作正常。

但是,当我尝试以编程方式建立对 CA 证书的信任时,我稍后对服务器的连接尝试被拒绝,尽管下面的代码不会产生错误。

因此我一定是把证书实现部分弄错了……有什么想法吗?

非常感谢!

NSString* certPath = [[NSBundle mainBundle] pathForResource:@"MyTestCA2" ofType:@"cer"]; //cer = CA certificate
NSData* certData = [NSData dataWithContentsOfFile:certPath];
SecCertificateRef cert;
if( [certData length] ) {
cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData);
if( cert != NULL ) {
CFStringRef certSummary = SecCertificateCopySubjectSummary(cert);
NSString* summaryString = [[NSString alloc] initWithString:(__bridge NSString*)certSummary];
NSLog(@"CERT SUMMARY: %@", summaryString);
certSummary = nil;
} else {
NSLog(@" *** ERROR *** trying to create the SSL certificate from data located at %@, but failed", certPath);
}
}

OSStatus err = noErr;
CFTypeRef result;
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
(__bridge id)kSecClassCertificate, kSecClass,
cert, kSecValueRef,
nil];
err = SecItemAdd((__bridge CFDictionaryRef)dict, &result);
if(err!=noErr) NSLog(@"error while importing");
if (err==errSecDuplicateItem) NSLog(@"Cert already installed");
NSLog(@":%i",(int)err);
assert(err==noErr||err==errSecDuplicateItem); // accept no errors other than duplicate
err = noErr;
SecTrustRef trust;
err = SecTrustCreateWithCertificates(cert, SecPolicyCreateBasicX509() ,&trust);
assert(err==noErr);
err = noErr;
CFMutableArrayRef newAnchorArray = CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);
CFArrayAppendValue(newAnchorArray,cert);
err = SecTrustSetAnchorCertificates(trust, newAnchorArray);
assert(err==noErr);
SecTrustResultType trustResult;
err=SecTrustEvaluate(trust,&trustResult);
assert(err==noErr);
cert=nil;

最佳答案

我没有尝试运行部分代码,但我有一些我知道有效的代码(在下面提供)。我用它来信任我的内部 CA。

err=SecTrustEvaluate(trust,&trustResult);
assert(err==noErr);

trustResult 是您感兴趣的内容,而不是 SecTrustEvaluate 返回的 errerr 告诉您 API 调用是否成功/失败;它不会告诉您信任评估的结果。

我认为您有两种策略。首先是在 trustResult 中使用值 kSecTrustResultProceedkSecTrustResultUnspecified 寻找“成功”。它的“成功”是因为它“提示”,它“尝试恢复”并且它“失败”。

第二个策略是 trustResult 中的“不失败”,值为 kSecTrustResultDenykSecTrustResultFatalTrustFailurekSecTrustResultOtherError。也就是说,只要 trustResult 不是这些值之一,就视为成功。忽略提示用户信任证书,因为他们不会理解提示并“点击通过”。

下面是我在 NSURLConnection 委托(delegate)的 -didReceiveAuthenticationChallenge: 中使用的代码。它需要一个 ASN.1/DER 编码的证书(名为 ca-cert.der)。它使用上述策略 1。如果您使用 #ifdef 0 中的代码,则使用策略 2。

我认为苹果的Overriding TLS Chain Validation Correctly , Apple 的技术说明 TN2232, HTTPS Server Trust Evaluation和 Apple 的技术问答 QA1360,Describing the kSecTrustResultUnspecified error可能对您有用。


- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:
(NSURLAuthenticationChallenge *)challenge
{
SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
return [[challenge sender] useCredential: [NSURLCredential credentialForTrust: serverTrust]
forAuthenticationChallenge: challenge];

if ([[[challenge protectionSpace] authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust])
{
do
{
SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
NSCAssert(serverTrust != nil, @"serverTrust is nil");
if(nil == serverTrust)
break; /* failed */

NSData* caCert = [NSData dataWithContentsOfFile:@"ca-cert.der"];
NSCAssert(caCert != nil, @"caCert is nil");
if(nil == caCert)
break; /* failed */

SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caCert);
NSCAssert(caRef != nil, @"caRef is nil");
if(nil == caRef)
break; /* failed */

NSArray* caArray = [NSArray arrayWithObject:(__bridge id)(caRef)];
NSCAssert(caArray != nil, @"caArray is nil");
if(nil == caArray)
break; /* failed */

OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
NSCAssert(errSecSuccess == status, @"SecTrustSetAnchorCertificates failed");
if(!(errSecSuccess == status))
break; /* failed */

SecTrustResultType result = -1;
status = SecTrustEvaluate(serverTrust, &result);
if(!(errSecSuccess == status))
break; /* failed */

NSLog(@"Result: %d", result);

/* https://developer.apple.com/library/ios/technotes/tn2232/_index.html */
/* https://developer.apple.com/library/mac/qa/qa1360/_index.html */
/* kSecTrustResultUnspecified and kSecTrustResultProceed are success */
if(result != kSecTrustResultUnspecified && result != kSecTrustResultProceed)
break; /* failed */

#if 0
/* Treat kSecTrustResultConfirm and kSecTrustResultRecoverableTrustFailure as success */
/* since the user will likely tap-through to see the dancing bunnies */
if(result == kSecTrustResultDeny || result == kSecTrustResultFatalTrustFailure || result == kSecTrustResultOtherError)
break; /* failed to trust cert (good in this case) */
#endif

// The only good exit point
return [[challenge sender] useCredential: [NSURLCredential credentialForTrust: serverTrust]
forAuthenticationChallenge: challenge];

} while(0);
}

// Bad dog
return [[challenge sender] cancelAuthenticationChallenge: challenge];
}

关于iOS - 以编程方式信任 CA(证书颁发机构),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25142357/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com