在Apple平台上,客户端既不检查CA的证书吊销列表(CRL),也默认情况下不使用OCSP。
但是,Apple平台支持OCSP装订,或者它们提供了一种称为“撤销增强”的机制,这实际上可能导致OCSP调用,请参阅下面的详细信息。
OCSP装订
首先对OCSP装订进行解释:
该在线证书状态协议(OCSP)装订,正式名称为TLS证书状态请求的扩展,是检查的X.509数字证书撤销状态的标准。1通过将由CA签名的带时间戳的OCSP响应(附加到初始TLS握手中)附加(“装订”),它允许证书的演示者承担提供在线证书状态协议(OCSP)响应所涉及的资源成本让客户与CA联系,以提高安全性和性能。
参见https://en.wikipedia.org/wiki/OCSP_stapling
OCSP和OCSP装订之间的区别
如果客户端以传统的OCSP流连接到服务器并检索证书,则它通过向CA发出请求来检查接收到的证书是否已被吊销。这具有一些缺点,例如,需要额外的网络连接,信息未加密,因此代表了数据隐私问题。
通过OCSP装订,服务器从CA请求签名的撤销信息,并将其添加到TLS握手中。
这也意味着,在使用OCSP装订时,您不会看到从iOS到CA服务器的OCSP请求。
OCSP装订的缺点
您要连接的服务器必须支持OCSP装订。这也不能防止恶意服务器。
这就是Apple提供撤销增强功能的主要原因。
苹果的撤销增强
运作方式如下:
- 证书透明度日志条目由Apple收集
- 通过此信息,Apple可以从CA收集有关吊销的信息
- 然后,这些汇总信息会自动自动定期提供给所有Apple客户
- 根据此信息,当iOS应用尝试使用吊销的证书连接到服务器时,它将通过OCSP执行附加检查。
需求
应用程序要支持此功能的唯一要求是,将使用的服务器证书添加到证书透明性日志中。通常,CA已经这样做了,但是您应该检查域证书是否在公共证书的活动透明日志中,例如,使用以下链接:https : //transparencyreport.google.com/https/certificates
WWDC 2017,会议701
有一个很棒的WWDC会议,其中详细介绍了此主题和Apple的动机:WWDC 2017,会议701:https : //developer.apple.com/videos/play/wwdc2017/701/
苹果工程师在12:10左右详细解释了整个撤销主题。她在15:30左右解释说,正常的OCSP将需要使用其他API。
在iOS上测试OCSP装订
为了进行测试,我们需要一台支持OCSP装订并使用吊销证书的
服务器:https : //revoked.grc.com(在此serverfault答案中找到此服务器:https : //serverfault.com/a/645066)
然后,我们可以尝试从iOS连接一个小型测试程序,该程序尝试下载HTML响应并将其输出到控制台。
根据上述WWDC会话中的信息,连接尝试应失败。
...
let session = URLSession(configuration: .default)
...
func onDownloadAction() {
let url = URL(string: "https://revoked.grc.com")!
self.download(from: url) { (result, error) in
if let result = result {
print("result: " + result)
} else {
print("download failed")
if let error = error {
print("error: \(error)")
}
}
}
}
func download(from url: URL, completion: @escaping(String?, Error?)->Void) {
let dataTask = self.session.dataTask(with: url) { data, response, error in
guard let data = data else {
if let error = error {
completion(nil, error)
return
}
completion(nil, NSError(domain: "DownloadFailure", code: 0, userInfo:nil))
return
}
guard let response = response as? HTTPURLResponse else {
completion(nil, NSError(domain: "ResponseFailure", code: 0, userInfo:nil))
return
}
print("http status: \(response.statusCode)")
let res = String(bytes: data, encoding: .utf8)
completion(res, nil)
}
dataTask.resume()
}
如果我们在iOS Simulator中执行上述例程,则可以使用Wireshark来检查是否将CA签名的带时间戳的OCSP响应装订到TLS握手中。
随着nslookup revoked.grc.com
我们获得了服务器的IP地址,并可以在Wireshark的带过滤器ip.addr==4.79.142.205
。
在屏幕截图中,您可以看到证书的状态为revoked
。
因此,看看Xcodes控制台,可以看到以下输出:
2019-10-12 21:32:25.734382+0200 OCSPTests[6701:156558] ATS failed system trust
2019-10-12 21:32:25.734526+0200 OCSPTests[6701:156558] Connection 1: system TLS Trust evaluation failed(-9802)
2019-10-12 21:32:25.734701+0200 OCSPTests[6701:156558] Connection 1: TLS Trust encountered error 3:-9802
2019-10-12 21:32:25.734787+0200 OCSPTests[6701:156558] Connection 1: encountered error(3:-9802)
2019-10-12 21:32:25.737672+0200 OCSPTests[6701:156558] Task <12408947-689F-4537-9642-C8F95E86CA62>.<1> HTTP load failed, 0/0 bytes (error code: -1200 [3:-9802])
download failed
error: Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x6000037f8510>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
"<cert(0x7fda78828200) s: revoked.grc.com i: DigiCert SHA2 Secure Server CA>",
"<cert(0x7fda7882b200) s: DigiCert SHA2 Secure Server CA i: DigiCert Global Root CA>"
), NSUnderlyingError=0x600000be9170 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x6000037f8510>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
"<cert(0x7fda78828200) s: revoked.grc.com i: DigiCert SHA2 Secure Server CA>",
"<cert(0x7fda7882b200) s: DigiCert SHA2 Secure Server CA i: DigiCert Global Root CA>"
)}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://revoked.grc.com/, NSErrorFailingURLStringKey=https://revoked.grc.com/, NSErrorClientCertificateStateKey=0}
iOS会终止尝试通过TLS错误连接到服务器的尝试。
测试已撤销.badssl.com
revoked.badssl.com不支持OCSP装订。
如果我们查看https://revoked.badssl.com的证书详细信息,我们可以发现:
如果下载.crl文件(2.5MB)并发出
openssl crl -inform DER -text -in ssca-sha2-g6.crl | grep 0371B58A86F6CE9C3ECB7BF42F9208FC
可以看到该证书已通过CRL吊销。
有趣的是,Safari,Chrome和iOS均未认识到该已撤销状态。仅Mozilla Firefox显示错误消息(对等证书已被吊销。错误代码:SEC_ERROR_REVOKED_CERTIFICATE)。
原因可能是该证书仅在几天前进行了更新,因此尚未在所有本地浏览器和操作系统的吊销列表中找到它。