Apple 플랫폼에서 클라이언트는 CA의 CRL (Certificate Revocation List)을 확인하거나 기본적으로 OCSP를 사용하지 않습니다.
그러나 Apple 플랫폼은 OCSP 스테이플 링을 지원하고 대안 적으로 OCSP 호출로 이어질 수있는 해지 향상 (Revocation Enhancement)이라는 메커니즘을 제공합니다 (아래 세부 사항 참조).
OCSP 스테이플 링
먼저 OCSP 스테이플 링에 대한 설명 :
온라인 인증서 상태 프로토콜 (OCSP) 스테이플 공식적으로 알려진 TLS 인증서 상태 요청 확장은 X.509 디지털 인증서의 해지 상태를 확인하기위한 표준이다. 1 인증서 발표자는 CA가 서명 한 타임 스탬프 된 OCSP 응답을 초기 TLS 핸드 셰이크에 추가 ( "스테이플 링")하여 OCSP (Online Certificate Status Protocol) 응답 제공과 관련된 리소스 비용을 부담 할 필요가 없습니다. 보안 및 성능 향상을 목표로 클라이언트가 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
이 주제와 Apple의 동기에 대해 자세히 설명하는 훌륭한 WWDC 세션이 있습니다 : WWDC 2017, 세션 701 : https://developer.apple.com/videos/play/wwdc2017/701/
약 12:10 분에 Apple 엔지니어가 전체 취소 주제를 자세히 설명합니다. 약 15:30에 그녀는 정상적인 OCSP가 추가 API를 사용해야한다고 설명합니다.
iOS에서 OCSP 스테이플 링 테스트
테스트를 위해 OCSP 스테이플 링을 지원하고 해지 된 인증서를 사용하는 서버가 필요합니다 : https://revoked.grc.com
(이 서버에서이 서버를 찾았습니다 : https://serverfault.com/a/645066 )
그런 다음 HTML 응답을 다운로드하여 콘솔에 출력하는 작은 테스트 프로그램으로 iOS에서 연결을 시도 할 수 있습니다.
위에서 언급 한 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 시뮬레이터에서 위의 루틴을 실행하면 Wireshark를 사용하여 CA가 서명 한 타임 스탬프 된 OCSP 응답이 TLS 핸드 셰이크에 스테이플 링되어 있는지 확인할 수 있습니다.
로 nslookup revoked.grc.com
우리 서버의 IP 주소를 얻을과 와이어 샤크에서 필터링 할 수 있습니다 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 ).
그 이유는 인증서가 며칠 전에 갱신되었으므로 아직 모든 로컬 취소 브라우저 및 운영 체제 목록에서 그 방법을 찾지 못했기 때문일 수 있습니다.