无法使用自定义CA打开安全websocket

我正在编写一个使用socket.io( socket.io-objc库)连接到本地和远程服务器的iOS应用程序。 我与远程服务器的连接已经使用TLS,没有任何问题。 远程服务器具有由知名CA签名的证书。 现在我想要保护本地连接。 但是,这些本地证书不可能由知名的CA签名。

到目前为止,我已经生成了一个自定义的CA证书,并用它来签署本地服务器的证书。 我相信这是工作,因为如果我手动安装CA证书到我的iPad我能够连接到服务器。

现在我试图在使用本文的应用程序中自动安装CA证书作为参考。 我遇到的问题是,虽然看起来我可以成功地将证书添加到我的应用程序的钥匙串中,但我的套接字连接似乎没有使用它。

在启动时,我的应用程序安装CA:

NSBundle *bundle = [NSBundle bundleForClass:[self class]]; NSData *iosTrustedCertDerData = [NSData dataWithContentsOfFile:[bundle pathForResource:@"myRootCA" ofType:@"der"]]; SecCertificateRef certificate = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef) iosTrustedCertDerData); CFDictionaryRef dict = (__bridge CFDictionaryRef)([NSDictionary dictionaryWithObjectsAndKeys: (__bridge id) (kSecClassCertificate), kSecClass, certificate, kSecValueRef, nil]); OSStatus err = SecItemAdd(dict, NULL); if (err == noErr) { NSLog(@"####### IT WORKS!!!!!!!!!"); } else if (err == errSecDuplicateItem) { NSLog(@"###### IT WAS ALREADY THERE!!!"); } else { NSLog(@"####### IT BROKEN!!!!!!!!"); } 

第一次运行时,打印出“IT WORKS”。 现在它打印出“IT WAS ALREADY THERE”。 这是预期的。 然后,当我尝试连接,我只是打开我的socket.io连接像正常

 SocketIO* socketIO = [[SocketIO alloc] initWithDelegate:self]; socketIO.useSecure = YES; [socketIO connectToHost:url onPort:port]; 

这导致错误:

该服务器的证书无效。 您可能连接到假装为“myserver.local”的服务器,这可能会使您的机密信息处于危险之中。

再次,如果我手动安装证书然后一切工作正常。 我所有的search如何以编程方式添加/信任证书点返回到SecItemAdd。 但是这似乎并没有为我工作。 是否可以使用socket.io-obj和pipe理套接字连接的SocketRocket库来添加/信任自定义的CA证书?

注意:我不想完全禁用证书validation,也不想接受所有自签名证书。 如果可能,我宁愿只接受由我的自定义CA(以及默认的可信CA)签名的证书。

我从来没有听说过能够将证书添加到应用程序的可信锚点。 通常,这只能通过iPhoneconfiguration实用程序在设备级完成。 那是“手动”的意思吗? (也就是说,安装它,以便Safari也会尊重它?)如果你读到你链接的博客文章的评论,你注意到希思(谁是一个非常聪明的人,所以我很小心,然后我不同意他)注意到:

没有添加证书到钥匙串。 我正在创build一个SecTrust对象并使用它来validation连接。 您只能通过iPhoneconfiguration实用程序将证书添加到钥匙串。 除非你添加一个证书钥匙链,我怀疑NSURLConnection会正常工作。

这匹配我的经验和testing。 (我不知道他为什么说“接下来,您可以将您的证书添加到您的应用程序的钥匙串中。当您希望iOS为您创build的每个新套接字信任您的证书时,这是适当的。

根据我的经验,您必须为NSURLConnection实现身份validation委托方法,并自己执行SecTrustEvaluate 。 这是一个例子。

记住,实际上只有一个钥匙链; 有只访问组,使它看起来像你有一个私人钥匙串。 就我所知,在这个钥匙链里只有一个可信的锚表,每个人都有分享。

这对socket.io没有什么帮助,因为它不允许你访问它的NSURLConnection委托方法。 您必须修改socket.io以接受信任锚。

您可能会发现演示文稿“ 实用安全性 ”很有用。 从第5页开始。这是上面的示例代码的来源。