iOS和SSL:无法验证自签名的服务器证书(iOS and SSL: Unable to valid

2019-06-25 10:21发布


我是相当新的使用SSL通道消费web服务。 相当不错的搜索后,我找到了使用NSURLConnection的委托API来进行SSL / HTTPS验证的方式。 以下是代码片段进行实际验证的事情:

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
[self printLogToConsole:@"Authenticating...."];
[self printLogToConsole:[NSString stringWithFormat:@"\n%@\n", [challenge description]]];
NSLog(@"\n\nserverTrust: %@\n", [[challenge protectionSpace] serverTrust]);

/* Extract the server certificate for trust validation
 */
NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];
assert(protectionSpace);
SecTrustRef trust = [protectionSpace serverTrust];    
assert(trust);
CFRetain(trust); // Make sure this thing stays around until we're done with it
NSURLCredential *credential = [NSURLCredential credentialForTrust:trust];


/* On iOS 
 * we need to convert it to 'der' certificate. It can be done easily through Terminal as follows:
 * $ openssl x509 -in certificate.pem -outform der -out rootcert.der
 */
NSString *path = [[NSBundle mainBundle] pathForResource:@"rootcert" ofType:@"der"];
assert(path);
NSData *data = [NSData dataWithContentsOfFile:path];
assert(data);

/* Set up the array of certificates, we will authenticate against and create credentials */
SecCertificateRef rtCertificate = SecCertificateCreateWithData(NULL, CFBridgingRetain(data));
const void *array[1] = { rtCertificate };
trustedCerts = CFArrayCreate(NULL, array, 1, &kCFTypeArrayCallBacks);
CFRelease(rtCertificate); // for completeness, really does not matter

/* Build up the trust anchor using our root cert */
int err;
SecTrustResultType trustResult = 0;
err = SecTrustSetAnchorCertificates(trust, trustedCerts);
if (err == noErr) {
    err = SecTrustEvaluate(trust, &trustResult);
}
CFRelease(trust); // OK, now we're done with it

[self printLogToConsole:[NSString stringWithFormat:@"trustResult: %d\n", trustResult]];

/* http://developer.apple.com/library/mac/#qa/qa1360/_index.html
 */
BOOL trusted = (err == noErr) && ((trustResult == kSecTrustResultProceed) || (trustResult == kSecTrustResultConfirm) || (trustResult == kSecTrustResultUnspecified));

// Return based on whether we decided to trust or not
if (trusted) {
    [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
    [self printLogToConsole:@"Success! Trust validation successful."];
} else {
    [self printLogToConsole:@"Failed! Trust evaluation failed for service root certificate.\n"];
    [[challenge sender] cancelAuthenticationChallenge:challenge];
}

}

但我发现了以下错误:

2012-06-11 17:10:12.541 SecureLogin[3424:f803] Error during connection: Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed. (NSURLErrorDomain error -1012.)" UserInfo=0x682c790 {NSErrorFailingURLKey=https://staging.esecure.url/authentication/signin/merchants, NSErrorFailingURLStringKey=https://staging.esecure.url/authentication/signin/merchants}


我使用,我从服务器得到它转换为“德”格式相同的证书。 我建立的应用程序适用于iOS 5.x的 我不知道我是否错过了什么。 让我知道你的建议。

谢谢。

编辑在这里输出的外观检验证书后:


让我知道如果有什么不对。

谢谢。

Answer 1:

我不知道,如果你的代码是有效还是无效,因为我用RestKit为使用REST接口,但导致最常见的问题NSURLErrorDomain Code=-1012是自签名的证书不具有subject alternative name扩展指向如果地址的Web服务。

要检查您的证书,下载Portecle应用程序 ,非常有用的,如果你需要寻找SSL证书里面。 运行它,并选择可审查>从菜单中检查证书并导航至您的证书。 你会看到基本信息,有关您的证书,现在按检查按钮,然后使用者替代名称,能让您的网络服务确保正确的IP地址是存在的。 如果没有,你需要在这个地方再次的信息创建证书。



Answer 2:

我没弄清楚如何解决这个问题。

我结束了比较客户端和服务器信任证书,逐字节。 虽然有可能是另一种方式来解决自签名证书的这样的问题,但这种解决方案所做的工作。 这里是我正在做的客户端和服务器证书的比较,逐字节,用他们的CFData对象(您也可以参考苹果公司提供“AdvancedURLConnections”示例代码):

success = NO;
        pServerCert = SecTrustGetLeafCertificate(trust);
        if (clientCert != NULL) {
            CFDataRef       clientCertData;
            CFDataRef       serverCertData;

            clientCertData = SecCertificateCopyData(clientCert);
            serverCertData   = SecCertificateCopyData(pServerCert);

            assert(clientCertData != NULL);
            assert(serverCertData   != NULL);

            success = CFEqual(clientCertData, serverCertData);

            CFRelease(clientCertData);
            CFRelease(serverCertData);
        }
        if (success) {
            [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
            [self printLogToConsole:@"Success! Trust validation successful."];
        } else {
            [self printLogToConsole:@"Failed! Trust evaluation failed for service root certificate.\n"];
            [[challenge sender] cancelAuthenticationChallenge:challenge];
        }

希望这会帮助别人,谁是寻找类似的问题的解决方案,

谢谢。



文章来源: iOS and SSL: Unable to validate self-signed server certificate