使用NSURLConnection连接到具有自签名证书的https时,kSecTrustResultRecoverableTrustFailure
我在这里看到几个问题,但没有一个帮助我。 人们主要解决的问题是重新生成服务器证书: kSecTrustResultRecoverableTrustFailure的原因是什么?
假设我需要使用自签名证书与服务器进行https连接。 我没有从服务器的任何内部数据,如其私钥。 例如,服务器是https://www.pcwebshop.co.uk/
据我所知,我可以将客户端证书捆绑到应用程序中,并将其用于validation。 我是否可以获得有效的客户端证书,而无需从服务器获取任何内部数据?
我在这里使用了一个教程http://www.indelible.org/ink/trusted-ssl-certificates
以下是我如何获得客户端证书
openssl s_client \ -showcerts -connect "${HOST}:443" </dev/null 2>/dev/null | \ openssl x509 -outform DER >"../resources/${HOST}.der"
这是代码(几乎不变):
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]; } - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { if ([self shouldTrustProtectionSpace:challenge.protectionSpace]) { [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; } else { [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge]; } } - (BOOL)shouldTrustProtectionSpace:(NSURLProtectionSpace *)protectionSpace { // load up the bundled certificate NSString *certPath = [[NSBundle mainBundle] pathForResource:protectionSpace.host ofType:@"der"]; if (certPath == nil) return NO; OSStatus status; NSData *certData = [[NSData alloc] initWithContentsOfFile:certPath]; CFDataRef certDataRef = (__bridge_retained CFDataRef)certData; SecCertificateRef cert = SecCertificateCreateWithData(NULL, certDataRef); // establish a chain of trust anchored on our bundled certificate CFArrayRef certArrayRef = CFArrayCreate(NULL, (void *)&cert, 1, NULL); SecTrustRef serverTrust = protectionSpace.serverTrust; status = SecTrustSetAnchorCertificates(serverTrust, certArrayRef); // status == 0 // verify that trust SecTrustResultType trustResult; status = SecTrustEvaluate(serverTrust, &trustResult); // status == 0 CFRelease(certArrayRef); CFRelease(cert); CFRelease(certDataRef); return trustResult == kSecTrustResultUnspecified; }
trustResult始终是kSecTrustResultRecoverableTrustFailure。
我究竟做错了什么? 谢谢。
更新 :好的,我发现原因是“服务器的证书不符合URL”。
是否可以通过忽略服务器证书的URL(主机名)来解决客户端问题?
假设我需要使用自签名证书与服务器进行https连接。 我没有从服务器的任何内部数据,如其私钥。
在这种情况下,您需要一个安全多元化战略。 Gutmann在他的“ 工程安全 ”( Engineering Security)一书中详细介绍了它。
缺点是:第一次遇到证书时会明智地validation证书。 您仍然可以使用大部分传统的PKI / PKIXtesting。 一旦证书通过了所有testing(除“可信根path”之外),则您将其称为“可信”。 这种策略被称为信任首先使用或TOFU。
在随后的连接中,由于您已经遇到证书或公钥,因此不需要再次使用TOFU。 在随后的连接中,确保证书或公钥是连续的(即不会更改),IP与以前遇到的区域相同,等等。如果证书发生更改,请确保它是因为自签名过期。 警惕意外的变化。
Here's the code (almost unchanged): ... trustResult == trustResult == kSecTrustResultUnspecified
对于kSecTrustResultUnspecified
,请参阅技术问答QA1360 。 本质上,它是一个可恢复的错误。 问答表示提示用户。 古特曼(和我)说如上所述使用安全多样化战略。
您需要将用户从循环中取出,因为他们总是会尽可能快地通过消息框来做出决定。 如果他们回答正确或错误,他们就不会死了 – 他们想看跳舞的兔子。
此外,安全多样化战略甚至适用于kSecTrustResultProceed
。 考虑一下: Diginotar和Trustwave都破坏了PKI {X},而Cocoa / CocoaTouch非常乐意返回kSecTrustResultProceed
。 它不是真正的Cocoa / CocoaTouch的缺点 – 有PKI {X}的架构缺陷。
是否可以通过忽略服务器证书的URL(主机名)来解决客户端问题?
这种打破了PKI {X}的目的。 如果您接受任何主机,任何公钥或任何签名,为什么还要打扰PKI {X}呢? PKI {X}中X509的全部要点是使用受信任的第三方签名(或本例中的自签名)将实体或主机绑定到公钥。
如果你不关心绑定,只需使用匿名Diffie-Hellman,并结束安全剧场。
- Delphi 10.1 Berlin idHTTP / IPv6 / iOS / Socket错误#51networking无法访问
- 在iOS应用程序中从http切换到https会在发布时引发出口符合性问题
- 通过https响应本机加载图像工作,而http不起作用
- SSL身份证书在iOS上运行HTTPS服务器
- 使用MonoTouch,HttpClient和Charles Proxy时出现HTTPstream量监控问题
- 如何使用AFNetworking比较SSL证书
- 什么是SSL固定? (介绍)
- Uber API端点不能与真正的服务器域一起工作,但可以很好地与沙箱配合使用
- 应用传输安全性已禁用,仍然收到SSL握手错误