Https安全通信(一)

iOS 9.0之后蘋果開始要求使用Https進(jìn)行通信。ATS是iOS9和OS X El Capitan的一個(gè)新特性。開啟該功能后,ATS對(duì)使用NSURLConnection, CFURL或NSURLSession 等APIs 進(jìn)行的網(wǎng)絡(luò)請(qǐng)求默認(rèn)強(qiáng)制使用HTTPS加密傳輸,目標(biāo)是提高Apple 操作系統(tǒng)以及應(yīng)用程序的安全性。蘋果公司官方文章指出,https必須符合ATS要求,服務(wù)器必須支持傳輸層安全(TLS)協(xié)議1.2以上版本;證書必須使用SHA256或更高的哈希算法簽名,并使用2048位以上RSA密鑰或256位以上ECC算法等等。

https概要

  • https協(xié)議基于http(超文本傳輸協(xié)議),在http通信基礎(chǔ)上對(duì)傳輸報(bào)文進(jìn)行加密,主要是為了保證通信雙方的數(shù)據(jù)不被竊取。在通信時(shí),服務(wù)器和客戶端各自提供自己的憑證,驗(yàn)證自己的身份后進(jìn)行通信. 這樣能減少不受信任的三方竊取信息。
  • PKI(公鑰基礎(chǔ)設(shè)施),是HTTPS的基礎(chǔ),PKI與非堆成秘鑰加密技術(shù)密切相關(guān),包括消息摘要,數(shù)字簽名,和加密服務(wù)。而數(shù)字證書以及證書機(jī)構(gòu)(CA -Certificate Authority)是PKI中重要的概念。
  • 數(shù)字證書在https中也起著至關(guān)重要的作用, 它是一個(gè)計(jì)算機(jī)文件,一般由可信任的證書機(jī)構(gòu)頒發(fā),他包含了證書所有者的一般信息(公開秘鑰)。并且能夠證明這個(gè)公鑰確實(shí)是證書所有者所合法擁有的。這一點(diǎn)是有CA對(duì)數(shù)字證書的簽名來保證的(簽名用到了信息摘要以及非對(duì)稱加密算法,使用CA的私鑰加密),在這里我門需要使用CA的數(shù)字證書(包含CA的公鑰)來驗(yàn)證簽名的合法性,那么我門如何驗(yàn)證CA數(shù)字證書的合法性呢?CA的信任鏈可以解決這個(gè)問題。一個(gè)CA的證書是由上一級(jí)CA簽發(fā)的,因此它的合法性由它的上一級(jí)CA來驗(yàn)證,其中最頂層的證書機(jī)構(gòu)被稱為根CA,它的證書被稱為根證書,如果一個(gè)鏈條的根證書是合法可信的,那么我們就認(rèn)為在這個(gè)鏈條上的所有CA以及它們所簽發(fā)的證書都是合法可信的。于是,最終的問題就是如何保證根證書的合法性呢?原來,我們所使用的基本計(jì)算機(jī)軟件,比如瀏覽器和服務(wù)器軟件,都會(huì)內(nèi)置根CA的自簽名證書,只要我們使用的基本軟件可信,那么就能保證根CA證書的合法有效。

https圖解

  • https雙向通信,只是在服務(wù)器身份確認(rèn)后,提供客戶端憑證再進(jìn)行一次客戶端的身份校驗(yàn)過程。首先客戶端和服務(wù)器需要經(jīng)過三次確認(rèn),生成二個(gè)隨機(jī)數(shù),并將服務(wù)器的證書提供給客戶端。前面兩個(gè)隨機(jī)數(shù)因?yàn)闀r(shí)明文傳輸?shù)?很容易給截取到,當(dāng)客戶端驗(yàn)證完服務(wù)器端的證書OK后,通過隨機(jī)數(shù)擴(kuò)展算法,按一定的規(guī)則生成第三個(gè)隨機(jī)數(shù),并用服務(wù)器的公鑰加密后發(fā)送給服務(wù)器.這樣客戶端和服務(wù)器均獲得三個(gè)隨機(jī)數(shù),從而可以生成雙方約定的會(huì)話秘鑰。 客戶端再將自己的證書發(fā)送給服務(wù)器端進(jìn)行驗(yàn)證,只要服務(wù)器驗(yàn)證通過,那么他們就開始使用這個(gè)隨機(jī)秘鑰進(jìn)行數(shù)據(jù)加密。實(shí)際上如果, 客戶端和服務(wù)器端協(xié)議版本號(hào)不一致,客戶端偏好設(shè)置中的加密算法列表里沒有服務(wù)器支持的任何一種加密算法,客戶端的憑證或服務(wù)器的憑證無法匹配,服務(wù)器域名不正確,或者證書過期等,都會(huì)導(dǎo)致通信失敗,這時(shí)候根據(jù)指定的警報(bào)協(xié)議 將相關(guān)的失敗信息通知到接收方。
  • 下圖為https的單向通信的主要流程,實(shí)際要比這個(gè)要復(fù)雜的多(忽略上面客戶端憑證的校驗(yàn)過程)。


    Snip20161204_8.png

https通信詳解

  • HTTPS是工作于SSL層上的HTTP協(xié)議,SSL(安全套接層)工作于TCP層上,向應(yīng)用層提供了兩個(gè)基本的安全服務(wù),認(rèn)證和保密。 SSL有三個(gè)子協(xié)議, 握手協(xié)議,記錄協(xié)議,警報(bào)協(xié)議。
    • 握手協(xié)議:
      1. 建立安全能力: 由客戶端發(fā)起,向服務(wù)器發(fā)送Client Hello消息,其中包含SSL版本,客戶端隨機(jī)數(shù)(用于生成秘鑰),會(huì)話號(hào),加密算法清單(客戶端所支持的加密算法),壓縮算法清單。服務(wù)器返回 Server Hello信息,其中包含SSL版本,服務(wù)器隨機(jī)數(shù)(用于生成秘鑰),會(huì)話號(hào),選擇加密算法,選擇的壓縮算法。
      2. 服務(wù)器認(rèn)證與秘鑰交換服務(wù)器是本階段發(fā)送信息的所有方,共三步
        • 第一步 : 證書,服務(wù)器將數(shù)字證書以及CA證書鏈發(fā)給客戶端,客戶端由此獲得服務(wù)器公鑰;客戶端還可以再這一步驗(yàn)證服務(wù)器是否可信.如果不可信則可以停止鏈接。并提醒用戶注意。
        • 第二步 : 服務(wù)器請(qǐng)求客戶端證書,客戶端認(rèn)證在SSL中是可選的,因此這一步也是可選的。
        • 第三步 : 服務(wù)器握手完成,發(fā)送這個(gè)消息后,服務(wù)器等待客戶端的響應(yīng)。
      3. 客戶端認(rèn)證與秘鑰交換
        • 客戶端是本階段的所有信息的發(fā)送方,分為三步
        • 第一步 : 證書,客戶端將客戶端的數(shù)字證書發(fā)送給服務(wù)器,里面包含了客戶端的公鑰,通常來說這個(gè)證書應(yīng)該是由服務(wù)提供著分發(fā)給客戶端,由指定的CA簽發(fā)的,因此服務(wù)器可以驗(yàn)證客戶端證書的合法性,并決定是否繼續(xù)。
        • 第二步 : 秘鑰交換,客戶端生成48字節(jié)的預(yù)備秘鑰,并用服務(wù)器端的公鑰加密,然后發(fā)送給服務(wù)器,這個(gè)預(yù)備秘鑰只有客戶端和服務(wù)器知道(與雙發(fā)在之后會(huì)話中使用的對(duì)成秘鑰相關(guān)),在這一步也間接的驗(yàn)證了服務(wù)器的合法性.因?yàn)橹挥袚碛信c證書對(duì)應(yīng)的私鑰才能解密出預(yù)備秘鑰。
        • 第三步 : 證書驗(yàn)證,客戶端還需要向服務(wù)器驗(yàn)證自己是真正的客戶端(數(shù)字證書無法證明它就是客戶端,擁有閾公鑰對(duì)應(yīng)的私鑰才是關(guān)鍵),為此客戶端把預(yù)備秘鑰,客戶隨機(jī)數(shù),服務(wù)器的隨記數(shù)組和起來,用私鑰對(duì)結(jié)果進(jìn)行簽名,發(fā)送給服務(wù)器,服務(wù)器利用客戶端公鑰就能夠的到原始的數(shù)據(jù),用來驗(yàn)證客戶端的真實(shí)性。(這里主要是對(duì) 客戶端隨記數(shù),服務(wù)器隨記數(shù),預(yù)備秘鑰)這個(gè)三個(gè)要素進(jìn)行判定是否有人竊取和串改。
      4. 完成: 在這個(gè)階段,客戶端和服務(wù)器各自獨(dú)立生成相同的主秘鑰和對(duì)成秘鑰,主秘鑰和對(duì)成秘鑰只有它們自己知道。主秘鑰和對(duì)成秘鑰是由 預(yù)備秘鑰,客戶端隨機(jī)數(shù)和服務(wù)器隨機(jī)數(shù)組和后,經(jīng)過消息摘要算法生成。
  • SSL握手完成之后,就會(huì)進(jìn)入回話階段:客戶端和服務(wù)器使用握手協(xié)議中生成的對(duì)成秘鑰進(jìn)行加密和解密以保證通信的安全。
  • 總的來說, 如果鑰完成HTTPS的雙向認(rèn)證需要以下秘鑰和證書:
    • 服務(wù)器端: 1.服務(wù)器私鑰, 2.由CA前發(fā)的含有服務(wù)器公鑰的數(shù)字證書, 3.CA的數(shù)字證書,在雙向驗(yàn)證過程中通常服務(wù)器可以自己作為證書機(jī)構(gòu),并且由服務(wù)器CA前發(fā)服務(wù)器證書和客戶端證書。
    • 客服端: 1.客戶端私鑰, 2. 由CA簽發(fā)的含有客戶端公鑰的數(shù)字證書。為了避免中間人攻擊,客戶端還需要內(nèi)置服務(wù)器證書,用來驗(yàn)證所連接的服務(wù)器是否是指定的服務(wù)器。(通常在一些服務(wù)器的網(wǎng)站或者app中,客服端憑證校驗(yàn)是默認(rèn)省略的,單向安全通信的,只對(duì)服務(wù)器的身份進(jìn)行校驗(yàn))。

https實(shí)踐

  • 在Apple Reference《Certificate,Key,and Trust Services Programming Guide》提供了https驗(yàn)證的框架, security.該框架包含了 https通信中信任對(duì)象, 同時(shí)也提供https加密中SAH,MD5,RSA,AES等算法的支持。
  • 基于AFNetworking https單向驗(yàn)證,系統(tǒng)框架已經(jīng)做了非常多的簡(jiǎn)化步驟,在AFSecurity這個(gè)庫中,框架內(nèi)部已經(jīng)做好了相關(guān)的判定,比如根據(jù)是否為私有證書,將提供的 證書對(duì)象設(shè)置為錨證書,對(duì)服務(wù)器返回的 信任對(duì)象進(jìn)行評(píng)估,如果通過則進(jìn)行安全通信,反之則取消通信。
       + (AFSecurityPolicy*)configSecurityPolicy {
         NSString *cerPath = [[NSBundle mainBundle]                 pathForResource:@"https" ofType:@"cer"];//證書的路徑
         NSData *certData = [NSData dataWithContentsOfFile:cerPath];
         AFSecurityPolicy* securityPolicy = [AFSecurityPolicy    policyWithPinningMode:AFSSLPinningModeCertificate];
         securityPolicy.allowInvalidCertificates = YES;  /**如果采用三方頒發(fā)的證書,則不使用自建證書驗(yàn)證服務(wù)器,由三方機(jī)構(gòu)驗(yàn)證*/
         securityPolicy.validatesDomainName = YES;
         securityPolicy.pinnedCertificates  = [NSSet setWithObject:certData];
         mgr.securityPolicy = securityPolicy;
         return securityPolicy;
         }
  • 基于AFNetworking雙向通信。
    • 在AFNetworking中進(jìn)行雙向通信,需要我們自己對(duì)挑戰(zhàn)認(rèn)證進(jìn)行定義,其中服務(wù)器身份驗(yàn)證部分,我們?nèi)匀豢梢匝赜蒙厦娴?security對(duì)象進(jìn)行自動(dòng)校驗(yàn),但是客戶端驗(yàn)證,就需要我們進(jìn)行實(shí)現(xiàn)了。
    • AFNetworking框架已經(jīng)為我們講調(diào)整驗(yàn)證的方法是用回調(diào)Block抽離出來。在使用時(shí)候我們只需鑰注冊(cè)該回調(diào)block,在對(duì)應(yīng)的block中實(shí)現(xiàn)當(dāng)收到驗(yàn)證服務(wù)器端憑證和需要提供客服端憑證的方法進(jìn)行處理.相關(guān)代碼實(shí)現(xiàn)方式如下.
    • 服務(wù)端驗(yàn)證: 首先需要對(duì)挑戰(zhàn)challege對(duì)象的保護(hù)空間進(jìn)行判定,獲取當(dāng)前的驗(yàn)證方式,如果是對(duì)服務(wù)器驗(yàn)證,則取出serverTrust對(duì)象,并通過設(shè)定錨證書,與我們定義的服務(wù)器證書的信任對(duì)象進(jìn)行比對(duì)和評(píng)估,判定是否正確,如果正確,則告訴challege挑戰(zhàn)發(fā)起者,下次繼續(xù)使用該憑證作為服務(wù)器的身份驗(yàn)證。
    • 客戶端驗(yàn)證: 將客服端憑證對(duì)象,通常都是由p12文件生成, 先將它轉(zhuǎn)換為CFData類型,再通過 valueForKey的方式,一層一層的將其撥開,取到最后的秘鑰,并生成NSURLCredential憑證對(duì)象。
    • AFNetworking框架最終生成的憑證對(duì)象,以及驗(yàn)證方式,通過block的回調(diào)的方式在 delegate挑戰(zhàn)認(rèn)證的方法中回調(diào)出去。
      + (void)configSSLChallage {
       AFHTTPSessionManager* mgr = [self shareInstance];
       __weak typeof(*&mgr)weakmgr = mgr;
       [mgr setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession * _Nonnull session, NSURLAuthenticationChallenge * _Nonnull challenge, NSURLCredential *__autoreleasing  _Nullable * _Nullable credential) {
          NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
           __autoreleasing NSURLCredential *_credential =nil;
        
           //server 端驗(yàn)證:
           if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
            NSLog(@"authorMethod:%@",challenge.protectionSpace.authenticationMethod);
            if([weakmgr.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host] ) {
             
               _credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
                if(credential) {
                    disposition =NSURLSessionAuthChallengeUseCredential;
                } else {
                    disposition =NSURLSessionAuthChallengePerformDefaultHandling;
                }
               } else {
                disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
                }
            } else {
              //client 客戶端驗(yàn)證:

                    NSLog(@"authorMethod:%@",challenge.protectionSpace.authenticationMethod);
            // client authentication
            SecIdentityRef identity = NULL;
            SecTrustRef trust = NULL;
            NSString *p12 = [[NSBundle mainBundle] pathForResource:@"client"ofType:@"p12"];
            NSFileManager *fileManager =[NSFileManager defaultManager];
            
            if(![fileManager fileExistsAtPath:p12])
            {
                NSLog(@"client.p12:not exist");
            }
            else
            {
                NSData *PKCS12Data = [NSData dataWithContentsOfFile:p12];
                
                if ([PLMNetWorkTool extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data])
                {
                    if (extractIdentityAndTrust((__bridge CFDataRef)(PKCS12Data), &identity, &trust)== noErr) {
                        SecCertificateRef certificate = NULL;
                        SecIdentityCopyCertificate(identity, &certificate);
                        const void*certs[] = {certificate};
                        CFArrayRef certArray =CFArrayCreate(kCFAllocatorDefault, certs,1,NULL);
                        
                        _credential =[NSURLCredential credentialWithIdentity:identity certificates:(__bridge  NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];
                        disposition =NSURLSessionAuthChallengeUseCredential;
                    }
                }
            }
         }
        *credential = _credential;
        return disposition;
         }];
 
        }

總結(jié): https涉及的內(nèi)容較多,如果不明白其中的具體原理,僅僅靠搬運(yùn)一份代碼,那么一段出現(xiàn)問題將是非常致命的。理解其中的緣由對(duì)于我們應(yīng)對(duì)https證書偽造,域名劫持,或是https會(huì)話秘鑰擴(kuò)展,https安全通信雙層加固非常重要。

參考文獻(xiàn): http://baike.baidu.com/link?url=QDGRYuHehLYwvUSNX_vH7xo8tQ8CJoDSSKeLP_PWzmohvk5E1E6RegmRGB0hERJW_0MqTBJn6sp6h65hLi_04a
http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,663評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,125評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,506評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,614評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,402評(píng)論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,934評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,021評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,168評(píng)論 0 287
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,690評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,596評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,784評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,288評(píng)論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,027評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,404評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,662評(píng)論 1 280
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,398評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,743評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容