使用NSURLConnection连接到具有自签名证书的https时,kSecTrustResultRecoverableTrustFailure [英] kSecTrustResultRecoverableTrustFailure when connecting to https with self-signed certificate using NSURLConnection

查看:323
本文介绍了使用NSURLConnection连接到具有自签名证书的https时,kSecTrustResultRecoverableTrustFailure的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里看到了一些问题,但没有一个问题对我有帮助。人们解决的问题主要是重新生成服务器证书: kSecTrustResultRecoverableTrustFailure是什么原因?

I've seen here a few questions but none of them helped me. People resolve issues mostly regenerating server certificates: What is the reason of kSecTrustResultRecoverableTrustFailure?

假设我需要使用自签名证书与服务器建立https连接。我没有来自服务器的任何内部数据,例如其私钥。例如,服务器是 https://www.pcwebshop.co.uk/

Suppose I need to make a https connection to server with self-signed certificate. I don't have any internal data from the server such as its private keys. For example the server is https://www.pcwebshop.co.uk/

据我了解,我可以将客户端证书捆绑到应用程序中并使用它进行验证。我是对的,我可以在没有来自服务器的任何内部数据的情况下获得有效的客户证书吗?

As far as I understand I can bundle a client certificate into app and use it for verification. Am I right I can obtain a valid client certificate without having any internal data from the server?

我在这里搜索了一个教程 http://www.indelible.org/ink/trusted-ssl-certificates

I've googled a tutorial here http://www.indelible.org/ink/trusted-ssl-certificates

以下是我获取客户证书的方式

Here's how I'm obtaining a client certificate

openssl s_client \
    -showcerts -connect "${HOST}:443" </dev/null 2>/dev/null | \
openssl x509 -outform DER >"../resources/${HOST}.der"

这是代码(几乎不变):

Here's the code (almost unchanged):

- (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。

trustResult is always kSecTrustResultRecoverableTrustFailure.

我做错了什么?谢谢。

更新:好的,我发现原因是服务器的证书与网址不匹配。

UPDATE: Ok, I found out that the reason is "Server's certificate does not match the URL".

是否可以通过忽略服务器证书的URL(主机名)来解决客户端问题?

Is it possible to fix the issue from the client side by ignoring the URL (hostname) of the server's certificate?

推荐答案


假设我需要使用自签名证书与服务器建立https连接。我没有来自服务器的任何内部数据,例如其私钥。

Suppose I need to make a https connection to server with self-signed certificate. I don't have any internal data from the server such as its private keys.

在这种情况下,您需要一个安全多样化策略。 Gutmann在他的书工程安全中详细介绍了它。

In this case, you need a security diversification strategy. Gutmann covers it in great detail in his book Engineering Security.

缺点:在您第一次遇到证书时明智地验证证书。您仍然可以使用大多数传统的PKI / PKIX测试。一旦证书通过所有测试(受信任的根路径除外),您就可以将其称为受信任。此策略称为Trust On First Use或TOFU。

The short of it: validate the certificate sensibly the first time you encounter it. You can still use most of the traditional PKI/PKIX tests. Once the certificate passes all tests (other than the "trusted root path"), you then call it "Trusted". This strategy is called Trust On First Use or TOFU.

在后续连接中,您不再需要TOFU,因为您已经遇到过证书或公钥。在后续连接中,您确保证书或公钥是连续的(即,不会更改),IP来自先前遇到的相同区域,等等。如果证书更改,请确保其因为自签名即将到期。警惕意外的变化。

In subsequent connections, you don't need TOFU again because you already encountered the certificate or public key. In the subsequent connections, you ensure the certificate or public key is continuous (i.e., does not change), the IP is from the same area as previously encountered, etc. If the certificate changes, then be sure its because the self signed is expiring. Be wary of unexpected changes.


Here's the code (almost unchanged):
...
trustResult == trustResult == kSecTrustResultUnspecified


对于 kSecTrustResultUnspecified ,请参阅技术Q& A QA1360 。从本质上讲,它是一个可恢复的错误。 Q& A表示提示用户。 Gutmann(和我)说要使用如上所述的安全多元化策略。

For kSecTrustResultUnspecified, see Technical Q&A QA1360. Essentially, its a recoverable error. The Q&A says to prompt the user. Gutmann (and I) say to use a security diversification strategy as described above.

你需要让用户退出循环,因为他们总会做出决定他们尽可能快地通过消息框。如果他们回答正确或错误就无所谓 - 他们希望看到跳舞的兔子。

You need to take the user out of the loop because they will always make a decision that gets them past the Message Boxes as quickly as possibly. It dies not matter if they answer right or wrong - they want to see the dancing bunnies.

此外,安全多元化策略甚至适用于 kSecTrustResultProceed 。考虑: Diginotar Trustwave 打破了PKI {X},Cocoa / CocoaTouch非常乐意返回 kSecTrustResultProceed 。它不是Cocoa / CocoaTouch的错 - PKI {X}有任何架构缺陷。

Also, the security diversification strategy even applies to kSecTrustResultProceed. Consider: Both Diginotar and Trustwave broke PKI{X}, and Cocoa/CocoaTouch was more than happy to return kSecTrustResultProceed. Its not really Cocoa/CocoaTouch's fault - there are architectural defects incumbent to PKI{X}.


是否可以通过忽略服务器证书的URL(主机名)来解决客户端问题?

Is it possible to fix the issue from the client side by ignoring the URL (hostname) of the server's certificate?

那种击败了PKI {X}的目的。如果您接受任何主持人,任何公钥或任何签名,为什么首先要打扰PKI {X}? PKI {X}中X509的重点是使用受信任的第三方签名(或在这种情况下为自签名)将实体或主机绑定到公钥。

That kind of defeats the purpose of PKI{X}. If you will accept any host, any public key or any signature, why even bother with PKI{X} in the first place? The whole point of X509 in PKI{X} is to bind a entity or host to a public key using a trusted third party signature (or self signed, in this case).

如果您不关心绑定,只需使用Anonymous Diffie-Hellman并结束安全影院。

If you don't care about the binding, just use Anonymous Diffie-Hellman and put an end to the security theater.

这篇关于使用NSURLConnection连接到具有自签名证书的https时,kSecTrustResultRecoverableTrustFailure的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆