1.前言
在目前的iOS,Android手機上,當手機應用進行SSL通信時,手機端默認是不會進行服務器證書是否失效的監測。
在iOS上,系統是會定期獲取所訪問服務器的證書信息然後出存在本地。
在Android端,系統是不會進行任何服務器證書的監測。
2.影響
如果應用在與服務器進行SSL通信時不進行任何的證書有效性檢測會造成用戶信息洩漏等安全問題。
3.解決方法
服務器證書有效性檢測有兩種方法,CRL檢測和OCSP檢測。
OCSP檢測主要的好處是時效性更有效率。本文主要從OCSP角度介紹實現方法。
3.1 iOS端
在iOS端,對應不同的通信方法有不同的服務器有效性檢測方法
WKWebView,NSURLSession,NSURLConnection等可以通過通用的方法解決。
核心代碼如下:
1 - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler 2 { 3 if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { 4 if ([[[UtilCrlOcsp alloc] init] isServerTrustProceedOrUnspecifiedWithAuthenticationChallenge:challenge]) { 5 completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]); 6 } else { 7 completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); 8 } 9 } 10 } 11 12 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error 13 { 14 [self updateTextViewMessage:error.description]; 15 } 16 17 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler 18 { 19 [self updateTextViewMessage:response.description]; 20 } 21 22 - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 23 { 24 if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { 25 if ([[[UtilCrlOcsp alloc] init] isServerTrustProceedOrUnspecifiedWithAuthenticationChallenge:challenge]) { 26 [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; 27 } else { 28 [challenge.sender cancelAuthenticationChallenge:challenge]; 29 } 30 } 31 }
而對於WebView,CFNetwork等的通信方法需要實現一些其它的方法。
具體可以參考蘋果官網的介紹。
3.2 Android端的實現
在Android端,利用CRL相關的API可以很快的檢測證書有效性。
但是對於OCSP的實現卻沒有任何相關函數支持,所以需要從零進行開發。
開發時可以參考bouncycastle的相關內容進行開發,本文主要介紹OCSP的實現過程
1 if (true || basicResponse.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider('BC').build(rootCert.getPublicKey()))) { 2 SingleResp[] responses = basicResponse.getResponses(); 3 4 byte[] reqNonce = getNonce(request.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce)); 5 byte[] resNonce = getNonce(basicResponse.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce)); 6 7 // validate the nonce if it is present 8 if (reqNonce == null || resNonce == null || Arrays.equals(reqNonce, resNonce)) { 9 10 for (int i = 0; i != responses.length;) { 11 putLog('OCSP certificate number ' + responses[i].getCertID().getSerialNumber()); 12 if (responses[i].getCertStatus() == CertificateStatus.GOOD) { 13 putLog('---OCSP status GOOD'); 14 return true; 15 } 16 else if (responses[i].getCertStatus() instanceof RevokedStatus) { 17 putLog('---OCSP status Revoked'); 18 return false; 19 } 20 else { 21 putLog('---OCSP status ' + responses[i].getCertStatus()); 22 return false; 23 } 24 } 25 }
4.總結
本文只是簡單的介紹了基於OCSP的證書有效性檢測,具體到真正的項目中該如何應用還需要coder自己的思考。