SSL Socket连接iOS

我想build立一个安全的连接到一个Java运行SSLServerSocket。

我已经创build了自己的根CA,并签署了使用此证书的Java SSLServerSocket的证书。

我想将这个根证书添加到我的应用程序,以便由根证书签名的任何证书将工作。

到目前为止,我有安全的连接工作正常通过设置读取和写入stream属性为:

NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys: (id)kCFStreamSocketSecurityLevelNegotiatedSSL, kCFStreamPropertySocketSecurityLevel, [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates, [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredRoots, [NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,nil]; 

我将证书添加到钥匙串中,如下所示:

 -(void)addRootCert{ NSString* rootCertPath = [[NSBundle mainBundle] pathForResource:@"rootCA" ofType:@"der"]; NSData* rootCertData = [NSData dataWithContentsOfFile:rootCertPath]; OSStatus err = noErr; SecCertificateRef rootCert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)rootCertData); NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge_transfer id)kSecClassCertificate, kSecClass, rootCert, kSecValueRef, nil]; err = SecItemAdd((__bridge CFDictionaryRef) dict, NULL); if (err == noErr) { NSLog(@"Sucessfully added root certificate"); }else if (err == errSecDuplicateItem){ NSLog(@"Root certificate already exists"); }else{ NSLog(@"Root certificate add failed"); } } 

这很好,但我想validation证书链,以便我的应用只接受由我的CA签名的证书(或默认的可信任证书)

我怎样才能做到这一点?

如果我设置kCFStreamSSLValidatesCertificateChain为yes,我得到的错误: CFNetwork SSLHandshake failed (-9807)但如果它不是,谁签署服务器证书无关紧要,它将连接无论(我认为是吗?)

谢谢!

Technote 2232 ,“HTTPS服务器信任评估”,应该有你需要的所有答案。 有文档和几个如何评估服务器信任的例子。

我也有同样的问题,手动添加证书确实解决了问题,这也意味着每当服务器上的证书发生变化时(例如,何时到期),在我的情况下,即将发生的在几天之内)。

如果您使用IP地址连接到套接字,并且证书是针对FQDN(完全限定的域名,即subdomain.example.com)的,则在操作系统检查证书时,将查看您连接的IP地址,将其与证书中的名称进行比较,并认为两者不同,导致链无法validation。

所以对于遇到这个问题的其他人,我build议在CFStreamCreatePairWithSocketToHost的第二个参数中使用FQDN而不是IP地址。 之后,它应该可以工作, 不必在证书中包含证书并手动validation。