Objective-C中,当进行加密通信的时候,可能会出现”NSStreamSocketSSLError”异常。扫描错误代码可以发现,其错误码为-9843,错误描述为”Informative SSL connection failed”,而其根本原因往往是证书验证失败。
处理这种错误的方法,一般有以下两种:
1. 忽略证书验证
一些情况下,我们可能并不关心对方是否是安全的,或者我们使用的是自签名证书,此时,我们可以忽略证书验证,直接进行加密通信,示例代码如下:
// 给流操作设置安全属性,此处省略流操作细节
NSDictionary *sslProperties = @{
(__bridge NSString*)kCFStreamSSLValidatesCertificateChain: @NO
};
[stream setProperty:sslProperties forKey:(__bridge NSString*)kCFStreamPropertySSLSettings];
// 进行加密通信
不过,需要注意的是,忽略证书验证可能会存在安全隐患,因此在实际应用中应该谨慎使用。
2. 添加根证书
在某些情况下,我们必须要验证对方的证书是否有效,此时我们需要添加对方的证书的根证书,才能进行加密通信。步骤如下:
2.1 获取对方证书
通常对方会提供一份证书给我们,我们可以从网络上下载对方的证书。以Apple的公钥为例,可以使用以下代码从官方网站上下载证书:
NSURL *url = [NSURL URLWithString:@"https://www.apple.com/"];
NSData *certData = [NSData dataWithContentsOfURL:[url URLByAppendingPathComponent:@"security/certs/GeoTrust_Primary_CA.pem"]];
2.2 导入根证书
我们需要将对方证书的根证书导入到我们的钥匙串中,使得我们可以进行验证。步骤如下:
- 双击证书文件(.pem)打开它
- 在”钥匙串访问”界面,选择证书,将其拖动到”我的证书”目录下,就会在钥匙串中添加一份新证书
- 右击新证书,选择”显示简介”,在对话框中,找到”信任”选项,选择”始终信任”
2.3 验证对方证书
在导入根证书后,我们可以在代码中进行证书验证,以确保对方的证书是真实有效的。示例代码如下:
// 给流操作设置安全属性,此处省略流操作细节
// 创建可信评审对象
SecTrustRef trust = (__bridge SecTrustRef)([sslProperties objectForKey:(__bridge id)_kCFStreamPropertySSLPeerTrust]);
SecTrustResultType resultType;
OSStatus status = SecTrustEvaluate(trust, &resultType);
BOOL certificateIsValid = (status == errSecSuccess) && (resultType == kSecTrustResultUnspecified);
if (!certificateIsValid) {
// 证书非法
[stream close];
return;
}
// 进行加密通信
需要注意的是,生产环境中,我们可以使用自己的证书进行验证,以确保通信安全。