8

我正在尝试设置与 java 运行 SSLServerSocket 的安全连接。

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

我想将此根证书添加到我的应用程序中,以便根证书签名的任何证书都可以使用。

到目前为止,通过将读写流属性设置为此,我的安全连接工作正常:

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");
}
}

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

我怎样才能做到这一点?

如果我设置kCFStreamSSLValidatesCertificateChain为是,我会收到错误:CFNetwork SSLHandshake failed (-9807)但如果不是,那么谁签署了服务器证书并不重要,它会连接无论如何(我认为这是对的?)

谢谢!

4

2 回答 2

6

技术说明 2232,“HTTPS 服务器信任评估”,应该有您需要的所有答案。有关于如何评估服务器信任的文档和几个示例。

于 2013-10-18T04:36:25.600 回答
0

我遇到了同样的问题,虽然手动添加证书确实解决了这个问题,但这也意味着每次服务器上的证书更改时都必须更新应用程序(例如当它过期时,在我的情况下,这将会发生几天之内)。

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

因此,对于遇到此问题的其他任何人,我建议在第二个参数中使用 FQDNCFStreamCreatePairWithSocketToHost而不是 IP 地址。之后,它应该可以工作,不必在捆绑包中包含证书并手动验证。

于 2016-02-22T18:02:18.297 回答