iOS安全系列之 HTTPS

本文參考鏈接:
Jamin
HTTPS信任證書的三種方法

在2016年底, Apple要求所有App適配App Transport Security,簡單的說就是除了特殊情況外,App跟服務(wù)端通信必須使用HTTPS協(xié)議,否則將阻止明文的HTTP請求,從2017年1月1日起,所有的新提交app默認是不允許使用 Allow Arbitrary Loads來繞過ATS限制的。

但是在2017年1月11日,Apple發(fā)布聲明宣布延長這個時限,提供開發(fā)者更多的時間來準(zhǔn)備適應(yīng),目前Apple仍未發(fā)布最新的截止日期。

雖然這個消息讓很多iOS開發(fā)者長出一口氣,至少目前不必擔(dān)心了,但是如果你不準(zhǔn)備好HTTPS,那么它終究是你頭頂上的達摩克利斯之劍,作為一名有追求的iOS開發(fā)者,有必要更深入的了解HTTPS。

引讀: 互聯(lián)網(wǎng)全站HTTPS的時代已經(jīng)到來

一. HTTPS

其實HTTPS從最終的數(shù)據(jù)解析的角度,與HTTP沒有任何的區(qū)別,HTTPS就是將HTTP協(xié)議數(shù)據(jù)包放到SSL/TSL層加密后,在TCP/IP層組成IP數(shù)據(jù)報去傳輸,以此保證傳輸數(shù)據(jù)的安全;而對于接收端,在SSL/TSL將接收的數(shù)據(jù)包解密之后,將數(shù)據(jù)傳給HTTP協(xié)議層,就是普通的HTTP數(shù)據(jù)。HTTP和SSL/TSL都處于OSI模型的應(yīng)用層。從HTTP切換到HTTPS是一個非常簡單的過程,在做具體的切換操作之前,我們需要了解幾個概念:

SSL/TSL

關(guān)于SSL/TSL,阮一峰的兩篇博客文章做了很好的介紹:

簡單的來說,SSL/TSL通過四次握手,主要交換三個信息:

  1. 數(shù)字證書:該證書包含了公鑰等信息,一般是由服務(wù)器發(fā)給客戶端,接收方通過驗證這個證書是不是由信賴的CA簽發(fā),或者與本地的證書相對比,來判斷證書是否可信;假如需要雙向驗證,則服務(wù)器和客戶端都需要發(fā)送數(shù)字證書給對方驗證。

  2. 三個隨機數(shù):這三個隨機數(shù)構(gòu)成了后續(xù)通信過程中用來對數(shù)據(jù)進行對稱加密解密的“對話密鑰”。首先客戶端先發(fā)第一個隨機數(shù)N1,然后服務(wù)器回了第二個隨機數(shù)N2(這個過程同時把之前提到的證書發(fā)給客戶端),這兩個隨機數(shù)都是明文的;而第三個隨機數(shù)N3(這個隨機數(shù)被稱為Premaster secret),客戶端用數(shù)字證書的公鑰進行非對稱加密,發(fā)給服務(wù)器;而服務(wù)器用只有自己知道的私鑰來解密,獲取第三個隨機數(shù)。只有服務(wù)端和客戶端都有了三個隨機數(shù)N1+N2+N3,然后兩端就使用這三個隨機數(shù)來生成“對話密鑰”,在此之后的通信都是使用這個“對話密鑰”來進行對稱加密解密。因為這個過程中,服務(wù)端的私鑰只用來解密第三個隨機數(shù),從來沒有在網(wǎng)絡(luò)中傳輸過,這樣的話,只要私鑰沒有被泄露,那么數(shù)據(jù)就是安全的。

  3. 加密通信協(xié)議:就是雙方商量使用哪一種加密方式,假如兩者支持的加密方式不匹配,則無法進行通信。

有個常見的問題,關(guān)于隨機數(shù)為什么要三個?只最后一個隨機數(shù)N3不可以么?

這是由于SSL/TLS設(shè)計,就假設(shè)服務(wù)器不相信所有的客戶端都能夠提供完全隨機數(shù),假如某個客戶端提供的隨機數(shù)不隨機的話,就大大增加了“對話密鑰”被破解的風(fēng)險,所以由三組隨機數(shù)組成最后的隨機數(shù),保證了隨機數(shù)的隨機性,以此來保證每次生成的“對話密鑰”安全性。

數(shù)字證書

數(shù)字證書是一個電子文檔,其中包含了持有者的信息、公鑰以及證明該證書有效的數(shù)字簽名。而數(shù)字證書以及相關(guān)的公鑰管理和驗證等技術(shù)組成了PKI(公鑰基礎(chǔ)設(shè)施)規(guī)范體系。一般來說,數(shù)字證書是由數(shù)字證書認證機構(gòu)(Certificate authority,即CA)來負責(zé)簽發(fā)和管理,并承擔(dān)PKI體系中公鑰合法性的檢驗責(zé)任;數(shù)字證書的類型有很多,而HTTPS使用的是SSL證書。

怎么來驗證數(shù)字證書是由CA簽發(fā)的,而不是第三方偽造的呢? 在回答這個問題前,我們需要先了解CA的組織結(jié)構(gòu)。首先,CA組織結(jié)構(gòu)中,最頂層的就是根CA,根CA下可以授權(quán)給多個二級CA,而二級CA又可以授權(quán)多個三級CA,所以CA的組織結(jié)構(gòu)是一個樹結(jié)構(gòu)。了解了CA的組織結(jié)構(gòu)后,來看看數(shù)字證書的簽發(fā)流程:

數(shù)字證書的簽發(fā)機構(gòu)CA,在接收到申請者的資料后進行核對并確定信息的真實有效,然后就會制作一份符合X.509標(biāo)準(zhǔn)的文件。證書中的證書內(nèi)容包括了持有者信息和公鑰等都是由申請者提供的,而數(shù)字簽名則是CA機構(gòu)對證書內(nèi)容進行hash加密后等到的,而這個數(shù)字簽名就是我們驗證證書是否是有可信CA簽發(fā)的數(shù)據(jù)。

接收端接到一份數(shù)字證書Cer1后,對證書的內(nèi)容做Hash等到H1;然后在簽發(fā)該證書的機構(gòu)CA1的數(shù)字證書中找到公鑰,對證書上數(shù)字簽名進行解密,得到證書Cer1簽名的Hash摘要H2;對比H1和H2,假如相等,則表示證書沒有被篡改。但這個時候還是不知道CA是否是合法的,我們看到上圖中有CA機構(gòu)的數(shù)字證書,這個證書是公開的,所有人都可以獲取到。而這個證書中的數(shù)字簽名是上一級生成的,所以可以這樣一直遞歸驗證下去,直到根CA。根CA是自驗證的,即他的數(shù)字簽名是由自己的私鑰來生成的。合法的根CA會被瀏覽器和操作系統(tǒng)加入到權(quán)威信任CA列表中,這樣就完成了最終的驗證。所以,一定要保護好自己環(huán)境(瀏覽器/操作系統(tǒng))中根CA信任列表,信任了根CA就表示信任所有根CA下所有子級CA所簽發(fā)的證書,不要隨便添加根CA證書。

了解了上面兩個概念之后,對HTTPS就有了個初步的了解,下面我們看如何在iOS上實現(xiàn)對HTTPS的支持。

二. 實現(xiàn)APP支持HTTPS

首先,需要明確你使用HTTP/HTTPS的用途,因為OSX和iOS平臺提供了多種API,來支持不同的用途,官方文檔《Making HTTP and HTTPS Requests》有詳細的說明,而文檔《HTTPS Server Trust Evaluation》則詳細講解了HTTPS驗證相關(guān)知識,這里就不多說了。本文主要講解我們最常用的NSURLSession支持HTTPS的實現(xiàn),以及怎么樣使用AFNetworking這個非常流行的第三方庫來支持HTTPS。本文假設(shè)你對HTTP以及NSURLSession的接口有了足夠的了解。

使用NSURLSession來支持HTTPS
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];  
_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];

NSURL *url = [NSURL URLWithString:@"https://域名"];  
 // 發(fā)起數(shù)據(jù)任務(wù)  
[[self.session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {  
NSLog(@"%@---%@",response,[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);  

// 在代理方法中實現(xiàn)證書的信任
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler {
    /*
     <NSURLProtectionSpace: 0x7fef2b686e20>:
     Host:mail.itcast.cn,
     Server:https,
     Auth-Scheme:NSURLAuthenticationMethodServerTrust,
     */
    // 判斷是否是信任服務(wù)器證書
    if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
        // 告訴服務(wù)器,客戶端信任證書
        // 創(chuàng)建憑據(jù)對象
        NSURLCredential *credntial = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
        // 通過completionHandler告訴服務(wù)器信任證書
        completionHandler(NSURLSessionAuthChallengeUseCredential,credntial);
    }
    NSLog(@"protectionSpace = %@",challenge.protectionSpace);
}

上面是代碼是通過系統(tǒng)默認驗證流程來驗證證書的。假如我們是自建證書的呢?這樣的話服務(wù)器的證書因為不是可信任的CA簽發(fā)的,所以直接使用進行驗證是不會成功的。又或者,即使服務(wù)器返回的證書是信任CA簽發(fā)的,又如何確定這證書就是我們想要的特定證書?這就需要先在本地導(dǎo)入證書,再驗證。

使用AFNetworking來支持HTTPS

AFNetworking是iOS/OSX開發(fā)最流行的第三方開源庫之一,其作者是非常著名的iOS/OSX開發(fā)者Mattt Thompson,其博客NSHipster也是iOS/OSX開發(fā)者學(xué)習(xí)和開闊技術(shù)視野的好地方。AFNetworking已經(jīng)將上面的邏輯代碼封裝好,甚至更完善,在AFSecurityPolicy文件中,有興趣可以閱讀這個模塊的代碼。 下面是代碼部分:

    // 1.初始化單例類
    AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];
    mgr.securityPolicy.SSLPinningMode = AFSSLPinningModeCertificate;
    // 2.設(shè)置證書模式
    NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"xxx" ofType:@"此處填文件的拓展名"];
    NSData * cerData = [NSData dataWithContentsOfFile:cerPath];
    mgr.securityPolicy.pinnedCertificates = [[NSArray alloc] initWithObjects:cerData, nil];
    // 客戶端是否信任非法證書
    mgr.securityPolicy.allowInvalidCertificates = YES;
    // 是否在證書域字段中驗證域名
    [mgr.securityPolicy setValidatesDomainName:NO];

最后建議采用本地導(dǎo)入證書的方式驗證證書,來保證足夠的安全性。
更多的驗證方法,請查看官方文檔《HTTPS Server Trust Evaluation》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 作者:Jaminzzhang 如何打造一個安全的App?這是每一個移動開發(fā)者必須面對的問題。在移動App開發(fā)領(lǐng)域,...
    __Lex閱讀 846評論 0 5
  • iOS安全系列之一:HTTPS 2014-10-21 如何打造一個安全的App?這是每一個移動開發(fā)者必須面對的問題...
    不作不會死閱讀 793評論 0 4
  • HTTPS其實HTTPS從最終的數(shù)據(jù)解析的角度,與HTTP沒有任何的區(qū)別,HTTPS就是將HTTP協(xié)議數(shù)據(jù)包放到S...
    七維樹閱讀 693評論 0 2
  • 其實,我對https以前只有一個大概的了解,最近工作中遇到一個問題從而將https協(xié)議做了一個徹底的學(xué)習(xí)和認知,下...
    一條魚的星辰大海閱讀 3,542評論 0 1
  • 原文地址:iOS安全系列之一:HTTPS 如何打造一個安全的App?這是每一個移動開發(fā)者必須面對的問題。在移動Ap...
    violafa閱讀 910評論 0 2

友情鏈接更多精彩內(nèi)容