iOS中的HTTPS認(rèn)證

一望门、HTTPS認(rèn)證

1. 會(huì)話認(rèn)證機(jī)制

iOS 中會(huì)話認(rèn)證機(jī)制共有四種,大體分為兩種類型:

  1. 單向認(rèn)證雙向認(rèn)證;
  2. NTLM 和 Kerberos崎场;

枚舉類如下:

會(huì)話認(rèn)證機(jī)制
  • 單向認(rèn)證
    指客戶端驗(yàn)證服務(wù)端的身份见秤,服務(wù)端不驗(yàn)證客戶端身份砂竖;

  • 雙向認(rèn)證
    指客戶端驗(yàn)證服務(wù)端身份真椿,服務(wù)端也認(rèn)證客戶端身份,未通過認(rèn)證的客戶端在握手階段直接斷開連接乎澄,禁止訪問服務(wù)器突硝;

  • NTLM 和 Kerberos
    用于早期的 Windows 中,不做深入研究置济;

說明:
HTTPS 通信中一般都是單向認(rèn)證解恰,這樣可以保證數(shù)據(jù)的加密傳輸,也能夠防止沒有證書的釣魚網(wǎng)站浙于。而雙向認(rèn)證一般用于企業(yè)來禁止接口被第三方調(diào)用和解析护盈。iOS 中的 NSURLSession 的默認(rèn)實(shí)現(xiàn)、AFN 的默認(rèn)實(shí)現(xiàn)都是單向認(rèn)證路媚,此時(shí)代理方法只會(huì)受到一種類型的回調(diào)黄琼,即: NSURLAuthenticationMethodServerTrust

雙向認(rèn)證建立在單向認(rèn)證的基礎(chǔ)上整慎,需要自己去額外實(shí)現(xiàn):

  1. 客戶端保存脏款、讀取并將證書發(fā)送給服務(wù)端;
  2. 服務(wù)端對證書實(shí)現(xiàn)自己的校驗(yàn)邏輯裤园;

雙向認(rèn)證中代理方法會(huì)收到兩個(gè)類型的回調(diào):

  1. NSURLAuthenticationMethodServerTrust :服務(wù)端發(fā)送證書給客戶端撤师,客戶端進(jìn)行證書校驗(yàn),默認(rèn)操作是使用跟證書(CA證書)進(jìn)行合法校驗(yàn)拧揽;
  2. NSURLAuthenticationMethodClientCertificate :服務(wù)端要求客戶端提供證書剃盾,此時(shí)客戶端應(yīng)將工程中的證書解析并傳遞給服務(wù)端。服務(wù)端一般也是做證書鏈校驗(yàn)淤袜,如果是有限訪問痒谴,還會(huì)做證書主體的校驗(yàn);

與會(huì)話層面的認(rèn)證機(jī)制相對的是特殊任務(wù)認(rèn)證機(jī)制:

特殊任務(wù)認(rèn)證

這些枚舉的意義是铡羡?积蔚??(見后文)

2. SSL/TLS

TLS (Transport Layer Security)就是 SSL(Secure Socket Layer)烦周,只不過版本不同而已:

SSL和TLS

SSL 和 HTTPS 的概念等不再贅述尽爆;

3. 認(rèn)證流程

HTTPS 中的單向認(rèn)證流程圖如下:

單向認(rèn)證流程圖

其具體的流程為:

  1. 客戶端向服務(wù)端發(fā)送請求建立連接的請求,并且附上客戶端支持的 SSL/TLS 協(xié)議版本读慎、加密算法漱贱、摘要算法,并且附上一個(gè)隨機(jī)數(shù)夭委;
  2. 服務(wù)端從客戶端支持的算法中選取一個(gè)回傳給客戶端幅狮,并且附上自己的證書,當(dāng)然證書中包含簽名、服務(wù)端公鑰彪笼。如果是非 Root CA 簽發(fā)的證書钻注,一般會(huì)包含兩個(gè)證書,一個(gè)是中間 CA 的證書(Root CA 簽發(fā)給中間 CA)配猫,一個(gè)是中間 CA 簽發(fā)給服務(wù)端的證書幅恋。另外,服務(wù)端也附上一個(gè)隨機(jī)數(shù)泵肄;
  3. 無論單向認(rèn)證還是雙向認(rèn)證捆交,這一步都需要對服務(wù)端的證書進(jìn)行 CA 驗(yàn)證,而這一步就是 AFN 和 NSURLSession 的主要功能點(diǎn)腐巢。證書包含 TBSCetificate品追、SignAlgorithm、SignValue冯丙,驗(yàn)簽主要流程就是對證書使用 SignAlgorithm 進(jìn)行加密肉瓦,一般是對 TBSCetificate 進(jìn)行摘要算法之后再 RSA,得到哈希值胃惜,對比證書中的 SignValue 是否一致泞莉;
  4. 客戶端再次生成一個(gè)隨機(jī)數(shù)(Premaster Random),至此船殉,客戶端已經(jīng)知道了三個(gè)隨機(jī)數(shù)鲫趁,可以生成最終的會(huì)話秘鑰了。如果是雙向認(rèn)證利虫,這里需要客戶端發(fā)送自己的證書到服務(wù)器挨厚;
  5. 客戶端使用服務(wù)端證書中的公鑰對第三個(gè)隨機(jī)數(shù)進(jìn)行加密,回傳給服務(wù)端糠惫;
  6. 服務(wù)端使用私鑰解密得到第三個(gè)隨機(jī)數(shù)疫剃。至此,服務(wù)端也知道了這三個(gè)隨機(jī)數(shù)硼讽,可以生成最終的會(huì)話秘鑰了慌申。如果是雙向認(rèn)證,這里服務(wù)器還需要對客戶端傳送過來的證書進(jìn)行驗(yàn)證理郑,驗(yàn)證錯(cuò)誤可能會(huì)直接斷開連接;
  7. 計(jì)算此前所有內(nèi)容的握手消息 hash 值咨油,并用"會(huì)話密鑰"加密后發(fā)送至客戶端用于驗(yàn)證您炉,此時(shí)的加密方式一般是對稱加密;
  8. 客戶端解密并計(jì)算握手消息的 hash 值役电,如果與服務(wù)端發(fā)來的 hash 一致赚爵,此時(shí)握手過程結(jié)束,可以正式開始接受和發(fā)送內(nèi)容了;

簡化版流程圖如下:

單向認(rèn)證流程圖

4. 各自使用場景

一般的 HTTPS 請求都采用單向認(rèn)證冀膝,只有極少數(shù)對安全性要求很高的企業(yè)采用雙向認(rèn)證如金融企業(yè)唁奢,或者是企業(yè)對涉及到核心業(yè)務(wù)的接口采用雙向認(rèn)證;

單向認(rèn)證中客戶端認(rèn)證服務(wù)端證書的特性就決定了窝剖,只要客戶端愿意且服務(wù)端的證書正常麻掸,那么任意客戶端都可以訪問該服務(wù)器;

雙向認(rèn)證中赐纱,除了客戶端對服務(wù)端進(jìn)行認(rèn)證脊奋,服務(wù)端還要對客戶端進(jìn)行認(rèn)證。因此疙描,服務(wù)端對客戶端證書的認(rèn)證邏輯就決定了客戶端是被動(dòng)的堪唐,能否訪問該服務(wù)器完全由服務(wù)端決定窟赏。有的服務(wù)端只是單純的對客戶端證書進(jìn)行 CA 認(rèn)證,還有的會(huì)對證書的主體進(jìn)行認(rèn)證,非白名單內(nèi)的主體不允許訪問服務(wù)器踏拜;

NTLM 和 Kerberos 用于早期的 Windows 中,本文不做過多了解:

NTLM工作流程

5. 雙向認(rèn)證和白名單

雙向認(rèn)證和白名單有這相同的作用噩茄,就是服務(wù)端限制某些客戶端的訪問囊颅,白名單機(jī)制的存在有這更方面成熟的實(shí)現(xiàn)機(jī)制,可能這就是雙向認(rèn)證不常用的原因火俄?

6. 證書體系的演變過程

  1. 簽名的產(chǎn)生

是指使用某種算法計(jì)算出元數(shù)據(jù)的哈希值犯建,以此確保元數(shù)據(jù)沒有被篡改,最初的簽名算法采用摘要算法瓜客,證書體系中的簽名采用摘要算法+ 非對稱加密的方式進(jìn)行簽名适瓦;

  1. 證書的產(chǎn)生

因?yàn)楹诳涂梢孕薷脑獢?shù)據(jù)的同時(shí)修改摘要算法得出的哈希值,所以出現(xiàn)了證書谱仪,其目的是通過非對稱加密來保證元數(shù)據(jù)的哈希值不被破解玻熙;

  1. 證書的組成

證書分為 TBSCertificate(To-Be-Signed) 和 Certificate,即待簽名的證書和簽名過的證書疯攒。TBSCertificate 證書中包含擁有者的各種信息嗦随,同時(shí)還包含擁有者的公鑰。我們一般說的證書是經(jīng)過簽名的敬尺,這種證書中除了包含 TBSCertificate 枚尼,還會(huì)包含簽名使用的算法、簽名值砂吞;

非對稱加密效率較低署恍,所以證書的簽名一般先對 TBSCertificate 使用摘要算法得到固定長度的哈希值,然后使用私鑰對這個(gè)哈希值進(jìn)行非對稱加密蜻直,最終得到簽名盯质,所以證書體系中的簽名已經(jīng)不是單純的摘要算法了袁串;

  1. 證書的權(quán)威性隱患

最初的證書是自簽名證書,擁有者使用自己的私鑰對 TBSCertificate 進(jìn)行簽名呼巷,如果黑客攻擊了證書發(fā)送者囱修,并將證書上的公鑰替換為自己的公鑰,甚至直接將擁有者的私鑰給竊取或者替換王悍,那么接收者接收到的也是被篡改過的數(shù)據(jù)破镰;

  1. Root CA 機(jī)構(gòu)的產(chǎn)生

自簽名證書中,私人的私鑰安全性隱患很大配名,因此才有了權(quán)威的 CA 機(jī)構(gòu)啤咽,證書體系中默認(rèn) CA 機(jī)構(gòu)的安全性不會(huì)被破解,所以理論上 CA 的私鑰不會(huì)被竊取渠脉。CA 機(jī)構(gòu)會(huì)對個(gè)人信息進(jìn)行驗(yàn)證宇整,并且使用自己的私鑰對 TBSCertificate 證書進(jìn)行簽名之后頒發(fā)給申請者;

CA 機(jī)構(gòu)的私鑰理論上絕對安全芋膘,公鑰會(huì)被嵌入到計(jì)算機(jī)基礎(chǔ)體系中鳞青,如被嵌入到操作系統(tǒng)、瀏覽器中为朋,所以瀏覽器可以直接使用 CA 的公鑰對證書進(jìn)行驗(yàn)簽臂拓;

驗(yàn)簽的流程就是先提取簽名時(shí)使用的簽名算法(signatureAlgorithm),這里主要是要知道簽名時(shí)摘要算法采用的哪一種习寸。然后提取出 TBSCertificate胶惰,使用摘要算法對 TBSCertificate 進(jìn)行哈希,得到 Hash1霞溪。接著孵滞,使用 CA 公鑰對簽名值(signatureValue)進(jìn)行解密,得到 Hash2鸯匹,如果 Hash1 = Hash2坊饶,則證書校驗(yàn)成功;

至此殴蓬,CA + 非對稱加密 + 摘要算法就組成了證書體系匿级;

  1. intermediate CA 的產(chǎn)生

Root CA 基本上就那幾個(gè),他們的公鑰會(huì)被嵌入到計(jì)算機(jī)基礎(chǔ)體系中染厅。如果直接使用 Root CA 的公鑰進(jìn)行簽發(fā)痘绎,那么一旦 Root CA 的私鑰發(fā)生變化,如撤銷肖粮、過期等简逮,牽連范圍極大。

所以 intermediate CA 出現(xiàn)了尿赚, intermediate CA 作為 Root CA 的代理散庶,先向 Root CA 申請證書,其流程和上面的基本一致凌净, intermediate CA 將自己的信息和公鑰發(fā)送給 Root CA 悲龟,Root CA 驗(yàn)證信息后頒發(fā) TBSCertificate 并使用自己的私鑰進(jìn)行簽名,最后頒發(fā)給 intermediate CA冰寻;

Root CA 只對 intermediate CA 頒發(fā)證書须教, intermediate CA 使用自己的私鑰對申請者的證書進(jìn)行簽名,這樣就實(shí)現(xiàn)了代理的作用斩芭;

一張圖做總結(jié):

證書體系

7. HTTPS 中的三個(gè)隨機(jī)數(shù)

  1. 為什么要三個(gè)隨機(jī)數(shù)轻腺?
  2. 為什么不直接使用 RSA 加密一個(gè)隨機(jī)數(shù)?

首先划乖,三個(gè)隨機(jī)數(shù)的正常使用流程如下:

HTTPS流程
  1. Client_Hello 階段贬养,客戶端明文傳輸 client_random 給服務(wù)端;
  2. Server_Hello 階段琴庵,服務(wù)端明文傳輸 server_random 給客戶端误算;
  3. Client_Hello_Done 階段,客戶端生成 premaster_random 并使用公鑰加密傳輸給服務(wù)端迷殿;
  4. Server_Hello_Done 階段儿礼,服務(wù)端使用私鑰解密得到 premaster_random;

最終客戶端和服務(wù)端都有三個(gè)隨機(jī)數(shù)庆寺,然后根據(jù)三個(gè)隨機(jī)數(shù)使用協(xié)議中的算法計(jì)算出一個(gè) master_random蚊夫,后續(xù)都使用 master_random 對報(bào)文進(jìn)行對稱加密之后傳輸;

這里有幾個(gè)重點(diǎn):

  1. 只用公鑰加密 premaster_random 懦尝,那么只要 premaster_random被破解知纷,整個(gè)過程就都被破解了;
  2. 既然 client_random 和 server_random 是明文的导披,那么 client_random 和 server_random 是否有必要屈扎?

要回答這兩個(gè)問題,這里就涉及到 HTTPS 中計(jì)算對稱加密最終 key 的兩種算法:

  • 算法一:RSA 加密算法

HTTPS 中如果采用 RSA 加密撩匕,也就是通過 premaster_random 這一個(gè)隨機(jī)數(shù)來計(jì)算最終的對稱秘鑰 master_random 鹰晨,最后客戶端使用 RSA 加密傳輸給服務(wù)端。后續(xù)服務(wù)端和客戶端都是用這個(gè)隨機(jī)數(shù)作為對稱加密的 key 進(jìn)行對稱加密止毕,這種情況有兩個(gè)問題:

  1. 偽隨機(jī)性:偽隨機(jī)數(shù)不一定隨機(jī)模蜡,被猜出來之后就被破解了;
  2. 向前攻擊:私鑰被竊取之后扁凛,之前攔截的報(bào)文都可以被解密忍疾;

流程如下:

RSA加密

根據(jù) RSA 算法的規(guī)則,RSA 只能暴力枚舉谨朝,算力很強(qiáng)的計(jì)算機(jī)都要枚舉 70 年卤妒,所以 RSA 基本無法破解甥绿。但是,需要注意的是则披,破解 HTTPS 的關(guān)鍵不在于破解 RSA共缕,而在于獲得對稱秘鑰。因?yàn)?RSA 算法只用在建立 HTTPS 的傳輸階段士复,后續(xù)加密都是使用對稱秘鑰图谷,所以一旦猜出了這個(gè)隨機(jī)數(shù),無需破解 RSA 就能破解 HTTPS阱洪。

因此便贵,HTTPS 的安全攻防歸根到底在于對稱秘鑰的加解密,只有這個(gè)隨機(jī)數(shù)越隨機(jī)冗荸,HTTPS 才越安全承璃。上述算法中,這個(gè)隨機(jī)數(shù)只在客戶端生成俏竞,其最大的問題在于隨機(jī)數(shù)的算法相對固定绸硕,那么就意味著:

  1. 偽隨機(jī)性低,猜出了客戶端使用的隨機(jī)算法就有可能猜出對稱秘鑰魂毁;
  2. 因?yàn)樗惴ü潭úE澹坏┎鲁隽艘粋€(gè)對稱秘鑰,可以根據(jù)該算法反推出之前會(huì)話中生成的對稱秘鑰席楚,即向前攻擊咬崔;

因此,開發(fā)出了三個(gè)隨機(jī)數(shù)的 HTTPS 加密烦秩。

  • 算法二:CS兩端一起生成三個(gè)隨機(jī)數(shù)
  1. 客戶端傳遞隨機(jī)數(shù) client_random垮斯;
  2. 服務(wù)端傳遞隨機(jī)數(shù) server_random;
  3. 前兩步因?yàn)殡p方?jīng)]有建立連接只祠,也就沒有公私鑰兜蠕,所以只能明文傳輸兩個(gè)隨機(jī)數(shù),但是到了第三部抛寝,客戶端接收到了服務(wù)端的公鑰熊杨,可以生成第三個(gè)隨機(jī)數(shù) pre_master,并且使用公鑰對第三個(gè)隨機(jī)數(shù)進(jìn)行加密之后傳輸給服務(wù)端盗舰;
  4. 客戶端可以優(yōu)先通過三個(gè)隨機(jī)數(shù)計(jì)算出最終的對稱秘鑰晶府,并且對之前的報(bào)文進(jìn)行加密,加這個(gè)哈希值傳遞給服務(wù)端钻趋;
  5. 服務(wù)端使用私鑰解密獲取到第三個(gè)隨機(jī)數(shù)之后川陆,也生成對稱秘鑰進(jìn)行驗(yàn)簽,驗(yàn)簽通過則告訴客戶端蛮位,后續(xù)直接使用對稱秘鑰加密较沪;

上述過程中鳞绕,客戶端和服務(wù)端在握手 hello 消息中明文交換了client_randomserver_random,使用 RSA 公鑰加密傳輸premaster secret尸曼,最后通過算法猾昆,客戶端和服務(wù)端分別計(jì)算 master secret。其中骡苞,不直接使用 premaster secret 的原因是:保證 secret 的隨機(jī)性不受任意一方的影響。

這種三個(gè)隨機(jī)數(shù)下的 HTTPS 已經(jīng)相當(dāng)安全了楷扬,理論上解幽,只要服務(wù)器的公鑰足夠長(比如2048位),那么Premaster secret可以保證不被破解烘苹。但是為了足夠安全躲株,我們可以考慮把握手階段的算法從默認(rèn)的RSA算法,改為 Diffie-Hellman算法(簡稱DH算法)镣衡。

  • 算法三:DH 加密算法
  1. 定義素?cái)?shù)g霜定、p(只有1和自身的因數(shù))
    g 和 p雙方都知道,這里假如 g = 7, p = 5廊鸥,實(shí)際上這兩個(gè)值都是很大的望浩。

  2. 雙方計(jì)算大數(shù) P = g^X mod p
    Server 生成隨機(jī)數(shù) X2,假設(shè) X2 = 5惰说,P2 = 7^5 mod 5 => 16807 對 5 取模磨德,結(jié)果為 2。
    Client 生成隨機(jī)數(shù) X1吆视,假設(shè) X1 = 2典挑,P1 = 7^2 mod 5 => 49 對 5 取模,結(jié)果為 4啦吧。

  3. 交換P1您觉、P2
    Client 有 p、g授滓、X1琳水、P2,Server有p褒墨、g炫刷、X2、P1郁妈。

  4. 計(jì)算密鑰 S
    利用S = g^X mod p 計(jì)算密鑰浑玛,對應(yīng) Client,S1 = P2^X1 mod p = 4噩咪,
    對應(yīng) Server顾彰,S2 = P1^X2 mod p = 4极阅,S1=S2 恒成立。

采用DH算法后涨享,Premaster secret不需要傳遞筋搏,雙方只要交換各自的參數(shù),就可以算出這個(gè)隨機(jī)數(shù)厕隧。上圖中奔脐,第三步和第四步由傳遞Premaster secret變成了傳遞DH算法所需的參數(shù),然后雙方各自算出Premaster secret吁讨。這樣就提高了安全性髓迎。

本質(zhì)上還是借鑒了分解質(zhì)因數(shù)只能暴力枚舉的原理;

流程如下:


DH算法

DH 算法原理:https://blog.csdn.net/mrpre/article/details/52608867

更加詳細(xì)的流程圖:

DH算法

如果不清楚上面的計(jì)算原理建丧,只需要知道 DH 算法通過 3 個(gè)隨機(jī)數(shù)來計(jì)算最終的 master_random 作為對稱加密的 key排龄,解決了偽隨機(jī)數(shù)不一定隨機(jī)的問題,還解決了 RSA 加密的向前攻擊的問題翎朱;

為什么需要三個(gè)隨機(jī)數(shù)橄维,總結(jié):

  1. 早期使用一個(gè)隨機(jī)數(shù),且采用 RSA 算法進(jìn)行傳輸拴曲,存在兩個(gè)嚴(yán)重的問題:偽隨機(jī)數(shù)不一定隨機(jī)争舞,RSA 被破解后(偽隨機(jī)數(shù)被猜出)存在向前攻擊的漏洞(根據(jù)算法可以猜出上一個(gè)隨機(jī)數(shù));
  2. 上述基礎(chǔ)上增加為 3 個(gè)隨機(jī)數(shù)疗韵,使得對稱秘鑰的隨機(jī)性不依賴于任何一方兑障,增加了破解難度, HTTPS 默認(rèn)采用這種握手規(guī)則蕉汪;
  3. DH 算法只傳遞參數(shù)流译,更加安全;

為什么偽隨機(jī)數(shù)不一定隨機(jī)者疤?只要這個(gè)隨機(jī)數(shù)是由確定算法生成的,那就是偽隨機(jī)福澡,也就是有規(guī)則的隨機(jī)。所以知道了算法驹马,下一個(gè)隨機(jī)數(shù)是可以被計(jì)算出來的革砸,所以,“隨機(jī)”這個(gè)屬性和算法本身就是矛盾的糯累。

附-破解 HTTPS 的三種方法:

破解 HTTPS 的三種方法

8. 三次握手四次分手

TCP報(bào)文格式:

TCP報(bào)文

序號:seq算利,用來標(biāo)識從TCP源端向目的端發(fā)送的字節(jié)流。tcp中傳輸數(shù)據(jù)時(shí)泳姐,會(huì)把數(shù)據(jù)中的每個(gè)字節(jié)用序號進(jìn)行標(biāo)志效拭,確保數(shù)據(jù)按順序傳輸

確認(rèn)號:ack,小寫的。只有ACK標(biāo)志位為1時(shí)缎患,確認(rèn)序號字段才有效慕的,ack=Seq+1。確認(rèn)方Ack=發(fā)起方Req+1挤渔,無論哪一端的確認(rèn)號都是如此肮街。比如A向B發(fā)送建立連接的請求時(shí),seq=x判导,B回復(fù)的報(bào)文中 ACK 標(biāo)志位為1嫉父,且確認(rèn)號就是ack=x+1,表示收到了序列號為x的報(bào)文眼刃。

標(biāo)志位:表示報(bào)文的六種格式熔号,為1時(shí)才有效,默認(rèn)為0鸟整;注意,ACK是標(biāo)志位朦蕴,而ack是確認(rèn)號篮条。

(A)URG:緊急指針(urgent pointer)有效。

(B)ACK:確認(rèn)序號有效吩抓。

(C)PSH:接收方應(yīng)該盡快將這個(gè)報(bào)文交給應(yīng)用層涉茧。

(D)RST:重置連接。

(E)SYN:發(fā)起一個(gè)新連接疹娶。

(F)FIN:釋放一個(gè)連接伴栓。

  1. 客戶端發(fā)送一個(gè)報(bào)文,SYN標(biāo)志位被標(biāo)志為1雨饺,表示這個(gè)報(bào)文的類型是請求建立鏈接钳垮。同時(shí),生成一個(gè)序號seq=x额港,發(fā)送給服務(wù)器饺窿。因?yàn)檫@個(gè)seq是第一個(gè)序號,所以也叫做Initial Sequence Number移斩,也就是ISN肚医,ISN不能是一個(gè)固定的值,在建立連接時(shí)向瓷,兩端都需要通過ISN算法來生成一個(gè)ISN并放在seq中肠套,以此來防止ISN攻擊。如果ISN固定猖任,那么根據(jù)遞進(jìn)+length(攜帶數(shù)據(jù)時(shí))或者+1(不攜帶數(shù)據(jù)時(shí))的規(guī)律你稚,攻擊者很容易猜出后續(xù)的seq。最終的報(bào)文為:seq=x,SYN=1
  2. 服務(wù)器收到SYN=1的報(bào)文之后知道了客戶端要建立連接入宦,于是發(fā)送一個(gè)報(bào)文,SYN標(biāo)志為1哺徊,ACK標(biāo)志也為1,表示這個(gè)報(bào)文是對SYN(建立連接)進(jìn)行應(yīng)答乾闰。同時(shí)落追,因?yàn)锳CK=1,需要設(shè)置確認(rèn)序號涯肩,確認(rèn)序號Ack=x+1轿钠,也就是客戶端發(fā)送來的第一個(gè)報(bào)文的序號+1,以此來表示服務(wù)端收到了剛剛客戶端所發(fā)送的序號為x(seq=x)的報(bào)文病苗。另外疗垛,服務(wù)端也需要發(fā)送一個(gè)序號,序號是用來確保TCP數(shù)據(jù)按順序傳輸?shù)牧螂藭r(shí)服務(wù)端時(shí)第一次發(fā)送報(bào)文贷腕,所以也需要生成一個(gè)ISN,所以最終的報(bào)文為:seq=y咬展,ack=x+1泽裳,另外標(biāo)志位中ACK=1,SYN=1破婆;
  3. 客戶端接收到報(bào)文后涮总,發(fā)送一個(gè)報(bào)文,ACK標(biāo)志位設(shè)置為1祷舀,表示這個(gè)報(bào)文是對服務(wù)端上一個(gè)報(bào)文的應(yīng)答瀑梗,SYN設(shè)置為0,表示這已經(jīng)是個(gè)應(yīng)答包了裳扯,而不是請求建立連接的報(bào)文抛丽。于此同時(shí),因?yàn)門CP中所有的數(shù)據(jù)都是按順序傳輸?shù)氖尾颍驗(yàn)榇藭r(shí)客戶端和服務(wù)端發(fā)送的報(bào)文中都不包含length铺纽,也就是沒有數(shù)據(jù),所以此時(shí)seq仍然為x哟忍,ack=y+1狡门,表示客戶端接收到了服務(wù)端剛剛發(fā)送的序號為y(seq=y)的報(bào)文。最終報(bào)文為seq=x锅很,ack=y+1其馏,ACK=1,SYN=0(表示該位無效)
  4. 至此爆安,完成了三次握手叛复,開始正式發(fā)送數(shù)據(jù),客戶端再次發(fā)送一個(gè)報(bào)文,seq=x褐奥,lenght=50粗仓,ack=y+1舱沧,表示仍然是對序號為y的服務(wù)端報(bào)文的響應(yīng)摩渺;

四次分手:

  1. 第一次揮手掰吕,客戶端根據(jù)當(dāng)前報(bào)文的序號,設(shè)置好 seq 和 ack呜笑,并且將 ACK 標(biāo)志位設(shè)置為 1 表示該包為回包夫否。另外,將 FIN 標(biāo)志位設(shè)置為 1叫胁,表示斷開連接凰慈。此時(shí),客戶端進(jìn)入 FIN_WAIT_1 狀態(tài)驼鹅,表示客戶端沒有數(shù)據(jù)要發(fā)送給服務(wù)端了微谓。
  2. 第二次揮手,服務(wù)端收到了客戶端發(fā)送的 FIN 報(bào)文段输钩,向客戶端回了一個(gè) ACK 報(bào)文段堰酿,表示收到上一個(gè) FIN 的報(bào)文了;
  3. 第三次揮手张足,服務(wù)端所有數(shù)據(jù)發(fā)送完畢之后,向客戶端發(fā)送 FIN 報(bào)文段坎藐,請求關(guān)閉連接为牍,同時(shí)服務(wù)端進(jìn)入 LAST_ACK 狀態(tài);
  4. 第四次揮手岩馍,客戶端收到服務(wù)端發(fā)送的 FIN 報(bào)文段后碉咆,向服務(wù)端發(fā)送 ACK 報(bào)文段,然后客戶端進(jìn)入 TIME_WAIT 狀態(tài)。服務(wù)端收到客戶端的 ACK 報(bào)文段以后蛀恩,就關(guān)閉連接疫铜。此時(shí),客戶端等待2MSL(指一個(gè)片段在網(wǎng)絡(luò)中最大的存活時(shí)間)后依然沒有收到回復(fù)双谆,則說明服務(wù)端已經(jīng)正常關(guān)閉壳咕,這樣客戶端就可以關(guān)閉連接了;

完整的通信流程:

TCP完整流程

9. 為什么握手需要三次分手需要四次

  • TCP中為什么握手需要三次
  1. 兩次不夠:兩次請求時(shí)顽馋,server 和 client 各自發(fā)送和接收到一個(gè)報(bào)文谓厘。對于server而言,相當(dāng)于接收到一個(gè)報(bào)文就從listen狀態(tài)切換到開啟狀態(tài)寸谜。如果網(wǎng)絡(luò)延遲竟稳,client發(fā)送了多次請求建立連接的報(bào)文,那么就會(huì)開啟多個(gè)請求。另外他爸,TCP是雙向協(xié)議聂宾,如果此時(shí)就開啟連接,如果server先發(fā)送數(shù)據(jù)诊笤,而client又沒有接收到server的第一個(gè)回包系谐,那么就只有server一方在發(fā)送數(shù)據(jù),相當(dāng)于一個(gè)人在電話的一頭巴拉一大堆盏混,但是對方信號已經(jīng)中斷蔚鸥,完全沒聽到。client完全接收不到许赃;所以止喷,在服務(wù)器接收到第三個(gè)報(bào)文之后才開啟連接,允許訪問混聊,此時(shí)才是最合適的弹谁;
  2. 四次多了:三次夠用,四次就多了句喜;

總結(jié):網(wǎng)絡(luò)存在延遲预愤、丟失的情況,兩次握手會(huì)導(dǎo)致服務(wù)端開啟多個(gè)無效連接咳胃,進(jìn)而導(dǎo)致服務(wù)端在傳送數(shù)據(jù)但是客戶端并沒有連接上的情況植康,而四次握手又多余了。

  • 為什么分手需要四次
  1. 客戶端發(fā)送FIN報(bào)文意味著不再向server發(fā)送數(shù)據(jù)展懈,但是還可以接受數(shù)據(jù)销睁;
  2. 服務(wù)端在三次握手時(shí),將ACK和SYN報(bào)文合并發(fā)送存崖,而在四次分手時(shí)冻记,因?yàn)榉?wù)端可能存在未發(fā)送的數(shù)據(jù),所以ACK和 FIN 報(bào)文一般都分開發(fā)送来惧,即在接收到client的FIN報(bào)文之后立馬發(fā)送ACK冗栗,但是在數(shù)據(jù)傳輸完畢之后再發(fā)送 FIN 報(bào)文;

總結(jié):客戶端請求斷開連接時(shí)供搀,server有可能存在未發(fā)送完畢的數(shù)據(jù)隅居,這種特性導(dǎo)致server將ACK和FIN報(bào)文分開發(fā)送,所以就會(huì)出現(xiàn)比三次握手時(shí)多一次的報(bào)文葛虐,三次握手時(shí)军浆,server將ACK和SYN合并發(fā)送了;

  • HTTPS中的四次握手:
  1. 客戶端請求并發(fā)送一個(gè)隨機(jī)數(shù)挡闰;
  2. 服務(wù)端回應(yīng)并發(fā)送證書乒融、公鑰和一個(gè)隨機(jī)數(shù)掰盘;
  3. 客戶端驗(yàn)證通過后,生成一個(gè)premaster_random赞季,使用公鑰加密之后傳遞給服務(wù)器愧捕,并根據(jù) DH 算法計(jì)算出 master_key,此為客戶端 finish 報(bào)文申钩?
  4. 服務(wù)端接收到后用私鑰解密得到premaster_random并根據(jù) DH 算法生成master_random次绘,hash 握手階段所有報(bào)文之后使用秘鑰加密傳輸給客戶端,此為服務(wù)端 finish 報(bào)文撒遣;
  5. 客戶端同樣也 hash 所有報(bào)文之后使用秘鑰進(jìn)行對稱加密邮偎,對比服務(wù)端給過來的值,如果一致則握手結(jié)束义黎,如果不一致則斷開連接禾进;

結(jié)果:客戶端和服務(wù)端的 master_random 是相同的,后面都使用這個(gè)數(shù)字作為對稱加密的 key 來對數(shù)據(jù)進(jìn)行對稱加密之后進(jìn)行傳輸廉涕;

二泻云、ATS

1. ATS簡介

ATS,即 App Transport Security狐蜕,ATS 默認(rèn)情況下要求 App 所有的請求都使用 HTTPS 連接宠纯,且對 HTTPS 認(rèn)證中的摘要算法版本、對稱算法版本等進(jìn)行要求层释。Apple 利用自己的強(qiáng)勢地位推動(dòng)了客戶端的安全性婆瓜。

2. ATS 的使用

  1. 默認(rèn)開啟

如果不額外在 info.plist 中設(shè)置 ATS,那么就相當(dāng)于開啟 ATS贡羔。

此時(shí)廉白,所有的連接/請求都會(huì)被 ATS 機(jī)制攔截并使用 ATS 中默認(rèn)的設(shè)置來進(jìn)行連接的認(rèn)證和建立,符合 ATS 要求的請求才能夠通過治力,否則會(huì)被拒絕,ATS 默認(rèn)策略的檢測包括且不限于:

  1. 證書鏈的驗(yàn)證(層層驗(yàn)簽勃黍,最終使用系統(tǒng)中的跟證書對 intermediate CA 進(jìn)行驗(yàn)簽)宵统,這個(gè)應(yīng)該對應(yīng)代碼中的 X509 認(rèn)證模式;

  2. TLS 最低版本驗(yàn)證覆获;

  3. 摘要算法最低版本驗(yàn)證马澈;

  4. 默認(rèn)會(huì)進(jìn)行域名驗(yàn)證,域名認(rèn)證就是對葉子節(jié)點(diǎn)的證書中的域名進(jìn)行對比弄息。AFN 早期版本默認(rèn)是 X509 認(rèn)證痊班,即只驗(yàn)簽,不認(rèn)證域名摹量,存在證書被劫持/替換的風(fēng)險(xiǎn)涤伐,該重大漏洞被曝出后 AFN 對其進(jìn)行了修復(fù)馒胆;

  5. 默認(rèn)策略沒有鎖定認(rèn)證(SSL Pinning Mode),而 AFN 中對此模式進(jìn)行了實(shí)現(xiàn)凝果;

  6. ATS 的三個(gè)設(shè)置項(xiàng)

最常用的兩個(gè)設(shè)置就是 NSAllowsArbitraryLoadsNSAllowsArbitraryLoadsInWebContent祝迂。兩者組合時(shí),會(huì)根據(jù)版本的不同(是否大于 iOS10)而有不同的表現(xiàn)器净。鑒于現(xiàn)在的 iOS9 版本已經(jīng)很少了型雳,可以直接使用 iOS10 的版本,兩個(gè)設(shè)置的優(yōu)先級:NSAllowsArbitraryLoadsInWebContent > NSAllowsArbitraryLoads山害。即設(shè)置了前者之后纠俭,后者會(huì)被忽略;

如果需要完全關(guān)閉 ATS浪慌,需要設(shè)置 NSAllowsArbitraryLoads = YES冤荆,并且在提交審核時(shí)進(jìn)行說明。

對于瀏覽器類 App眷射,如果只是允許瀏覽器中使用非安全的請求(HTTP)匙赞,那么只需要設(shè)置 NSAllowsArbitraryLoadsInWebContent = YES 即可。

另外妖碉,還可以使用 NSExceptionDomains 來設(shè)置允許 HTTP 請求的白名單域名涌庭,這種設(shè)置相對于直接關(guān)閉 ATS 更容易過審,使用如下:

NSExceptionDomains

3. 驗(yàn)證域名是否符合 ATS

可以直接使用該網(wǎng)站來檢測所請求的域名是否符合 ATS 標(biāo)準(zhǔn):https://myssl.com/ats.html?domain=mobi.yocaigs.com&port=443

如圖:

ATS檢測

ATS 的具體要求可以再官方文檔中查閱:https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW35

  • 總結(jié)

綜上欧宜,如果公司使用的證書是 CA 申請下來的坐榆,且服務(wù)器端支持的加密算法符合 ATS 的要求,那么無論是 NSURLSession 還是 AFNetworking冗茸,都是可以直接進(jìn)行網(wǎng)絡(luò)請求的席镀,Apple 已經(jīng)完成了 HTTPS 中客戶端對服務(wù)器證書的驗(yàn)證操作,不需要開發(fā)者額外實(shí)現(xiàn)而且安全性能夠得到保證夏漱。

所以豪诲,ATS 是 Apple 對客戶端請求的安全標(biāo)準(zhǔn)和實(shí)現(xiàn)(封裝);

ATS(NSURLSession)中對 HTTPS 的默認(rèn)實(shí)現(xiàn)采用的是單向認(rèn)證策略挂绰,如果需要使用雙向認(rèn)證屎篱,則需要自己攔截 NSURLAuthenticationMethodClientCertificate 并提供客戶端的證書;

三葵蒂、證書鎖定認(rèn)證(SSL Pinning Mode)

1. 證書鎖定認(rèn)證簡介

  • 概念
    證書鎖定(SSL/TLS Pinning)顧名思義交播,將服務(wù)器提供的 SSL/TLS 證書內(nèi)置到移動(dòng)端開發(fā)的APP客戶端中,當(dāng)客戶端發(fā)起請求時(shí)践付,通過比對內(nèi)置的證書和服務(wù)器端證書的內(nèi)容秦士,以確定這個(gè)連接的合法性。

  • 產(chǎn)生原因
    因?yàn)?CA 證書簽發(fā)機(jī)構(gòu)也存在被黑客入侵的可能性永高,同時(shí)移動(dòng)設(shè)備也面臨內(nèi)置證書被篡改的風(fēng)險(xiǎn)隧土,或者是用戶信任了不該信任的證書提针,這些情況都有可能導(dǎo)致證書鏈的不可靠。鎖定認(rèn)證模式本質(zhì)是為了規(guī)避用戶信任鏈不可靠帶來的安全問題次洼;

  • 原理
    我們需要將 APP 代碼內(nèi)置僅接受指定域名的證書关贵,而不接受操作系統(tǒng)或?yàn)g覽器內(nèi)置的CA根證書對應(yīng)的任何證書,通過這種授權(quán)方式卖毁,保障了 APP 與服務(wù)端通信的唯一性和安全性揖曾,因此我們移動(dòng)端APP與服務(wù)端(例如 API 網(wǎng)關(guān))之間的通信是可以保證絕對安全。

2. 使用證書簽名進(jìn)行證書鎖定認(rèn)證(Certificate Mode)

此種模式下亥啦,App 需要驗(yàn)證證書的簽名炭剪,步驟如下:

  1. 服務(wù)端申請證書并將其內(nèi)置到 App(或客戶端) 中;
  2. 客戶端在 HTTPS 認(rèn)證的第二步接收到服務(wù)端發(fā)送過來的證書翔脱;
  3. 將服務(wù)端證書的簽名和內(nèi)置證書的簽名進(jìn)行對比奴拦,一致則校驗(yàn)通過,否則斷開連接届吁;

理論上應(yīng)該也可以在雙向認(rèn)證中错妖,客戶端發(fā)送證書給服務(wù)端進(jìn)行驗(yàn)證;

3. 使用公鑰進(jìn)行證書鎖定認(rèn)證(PublicKey Mode)

使用簽名校驗(yàn)的方式有一個(gè)缺點(diǎn):

  • CA 簽發(fā)證書都存在有效期問題疚沐,所以缺點(diǎn)是在證書續(xù)期后需要將證書重新內(nèi)置到 APP 中暂氯;

而公鑰驗(yàn)證可以規(guī)避掉這個(gè)缺點(diǎn),起流程如下:

  1. 服務(wù)端申請證書并將其內(nèi)置到 App(或客戶端) 中亮蛔;
  2. 客戶端在 HTTPS 認(rèn)證的第二步接收到服務(wù)端發(fā)送過來的證書并提取出公鑰痴施;
  3. 將提取出來的公鑰和本地內(nèi)置證書的公鑰進(jìn)行比對;

我們在制作證書密鑰時(shí)究流,公鑰在證書的續(xù)期前后都可以保持不變(即密鑰對不變)辣吃,所以可以避免證書有效期問題;

TBSCetificate 包含有效期這個(gè)字段芬探,頒發(fā)機(jī)構(gòu)是對 TBSCertificate 進(jìn)行簽名的神得,所以有效期發(fā)生變化則整個(gè)簽名都會(huì)發(fā)生變化。所以證書一旦過期偷仿,就需要更新 App 中的內(nèi)置證書哩簿,對于 iOS 而言就需要發(fā)布新的版本,加之版本的兼容會(huì)比較復(fù)雜炎疆,所以公鑰驗(yàn)證是一種比較合適的方案卡骂;

4. 相關(guān)的 openSSL 指令

  1. 獲取移動(dòng)端所需證書

如果采用證書鎖定方式(Certificate Mode)国裳,則獲取證書的摘要 hash形入,以 infinisign.com 為例:

## 在線讀取服務(wù)器端.cer格式證書
openssl s_client -connect infinisign.com:443 -showcerts < /dev/null | openssl x509 -outform DER > infinisign.der
## 提取證書的摘要hash并查看base64格式
openssl dgst -sha256 -binary infinisign.der | openssl enc -base64
wLgBEAGmLltnXbK6pzpvPMeOCTKZ0QwrWGem6DkNf6o=

所以其中的wLgBEAGmLltnXbK6pzpvPMeOCTKZ0QwrWGem6DkNf6o=就是我們將要進(jìn)行證書鎖定的指紋 (Hash) 信息。

  1. 獲取移動(dòng)端所需公鑰

如果采用公鑰鎖定方式(PublicKey Mode)缝左,則獲取證書公鑰的摘要hash亿遂,以infinisign.com為例

// 讀取服務(wù)器端證書的公鑰
openssl x509 -pubkey -noout -in infinisign.der -inform DER | openssl rsa -outform DER -pubin -in /dev/stdin 2>/dev/null > infinisign.pubkey

// 提取公鑰的摘要hash并查看base64格式
openssl dgst -sha256 -binary infinisign.pubkey | openssl enc -base64
bAExy9pPp0EnzjAlYn1bsSEGvqYi1shl1OOshfH3XDA=

所以其中的bAExy9pPp0EnzjAlYn1bsSEGvqYi1shl1OOshfH3XDA=就是我們將要進(jìn)行證書鎖定的指紋 (Hash) 信息浓若。

5. 鎖定認(rèn)證總結(jié)

  1. 鎖定認(rèn)證是為了解決終端證書鏈不可靠所引發(fā)的問題,是一種相對終極的解決方案蛇数;
  2. 證書鎖定模式就是驗(yàn)證 TBSCertificate 的簽名挪钓,其缺點(diǎn)是證書證書過期、失效時(shí)耳舅,需要頻繁更新終端內(nèi)嵌的證書碌上;
  3. 公鑰鎖定的方式只認(rèn)證公鑰,只要證書擁有者的私鑰不變浦徊,就不需要更新終端內(nèi)嵌的證書馏予;

四、AFN 鑒權(quán)源碼解讀

見文章:AFN中的鑒權(quán)

五盔性、源碼解讀

1. 可選的鑒權(quán)策略

typedef NS_ENUM(NSInteger, XKHTTPClientSSLChallengeMode) {
    XKHTTPClientSSLChallengeModeNone, // 忽略
    XKHTTPClientSSLChallengeModeSimple, // 不校驗(yàn)host
    XKHTTPClientSSLChallengeModeFull // 正常校驗(yàn)
};
  1. 不校驗(yàn)霞丧,對于訪問的 server 直接信任。
    此時(shí)冕香,可以訪問自簽名證書的網(wǎng)站蛹尝、證書過期的網(wǎng)站;

  2. 不校驗(yàn)域名
    此時(shí)悉尾,使用 X509 的規(guī)則對證書進(jìn)行校驗(yàn)突那,只要證書符合規(guī)則,且該證書的根節(jié)點(diǎn)存在于當(dāng)前機(jī)器的證書鏈中焕襟。另外陨收,如果自身機(jī)器中信任了某個(gè)證書,那么該證書會(huì)被添加到證書鏈中鸵赖,使用該證書作為根節(jié)點(diǎn)的證書也會(huì)通過校驗(yàn)务漩,所以是存在風(fēng)險(xiǎn)的;

  3. 正常校驗(yàn)
    此時(shí)走 Apple 中 ATS 的默認(rèn)實(shí)現(xiàn)它褪,檢測證書且校驗(yàn)域名饵骨;

代碼如下:

-(void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {

    NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    NSURLCredential * credential = nil;

    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        if (self.sslChallengeMode == XKHTTPClientSSLChallengeModeNone) {
            // 使用服務(wù)端的證書對服務(wù)端進(jìn)行校驗(yàn),那肯定是怎樣都通過,自簽名證書都能通過
            disposition = NSURLSessionAuthChallengeUseCredential;
            credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
        } else if(self.sslChallengeMode == XKHTTPClientSSLChallengeModeSimple) {
            SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
            NSArray * policies = @[ (__bridge_transfer id)SecPolicyCreateBasicX509() ];
            SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
            SecTrustResultType result;
            if(SecTrustEvaluate(serverTrust, &result) == errSecSuccess &&
               (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed)) {
                // x509認(rèn)證,不會(huì)對服務(wù)端證書中的域名和請求的域名進(jìn)行一致性校驗(yàn)
                // 校驗(yàn)成功,則直接傳遞服務(wù)端證書來對服務(wù)端鑒權(quán)進(jìn)行校驗(yàn),即:怎樣都會(huì)成功
                disposition = NSURLSessionAuthChallengeUseCredential;
                credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            } else {
                // x509校驗(yàn)失敗,則走默認(rèn)的校驗(yàn)邏輯
                disposition = NSURLSessionAuthChallengePerformDefaultHandling;
            }
        } else {
            // 默認(rèn)校驗(yàn)邏輯:ATS,即對證書錨點(diǎn)、證書鏈進(jìn)行校驗(yàn)且會(huì)對證書中的域名和請求的域名的一致性進(jìn)行校驗(yàn)
            disposition = NSURLSessionAuthChallengePerformDefaultHandling;
        }
    } else {
        disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    }

    if (completionHandler) {
        completionHandler(disposition, credential);
    }
}

2. Hybrid 容器的鑒權(quán)策略

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
    NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    NSURLCredential * credential = nil;

    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        disposition = NSURLSessionAuthChallengeUseCredential;
        credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
    }

    if (completionHandler) {
        completionHandler(disposition, credential);
    }
}
  1. 如果是客戶端驗(yàn)證服務(wù)端茫打,直接信任居触;
  2. 如果是其他驗(yàn)證操作,直接采用默認(rèn)方式進(jìn)行校驗(yàn)老赤;

對于容器而言轮洋,這樣做是合理的,因?yàn)闉g覽器可能會(huì)訪問不安全的網(wǎng)站抬旺;

3. SDWebImage 的鑒權(quán)策略

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
    
    NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
    __block NSURLCredential *credential = nil;
    
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        if (!(self.options & UPSDWebImageDownloaderAllowInvalidSSLCertificates)) {
            disposition = NSURLSessionAuthChallengePerformDefaultHandling;
        } else {
            credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
            disposition = NSURLSessionAuthChallengeUseCredential;
        }
    } else {
        if (challenge.previousFailureCount == 0) {
            if (self.credential) {
                credential = self.credential;
                disposition = NSURLSessionAuthChallengeUseCredential;
            } else {
                disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
            }
        } else {
            disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
        }
    }
    
    if (completionHandler) {
        completionHandler(disposition, credential);
    }
}
  1. 如果允許無效證書弊予,則直接信任;
  2. 如果不允許开财,則采用 NSURLSession/Task 的默認(rèn)策略汉柒;
  3. 如果不是客戶端驗(yàn)證服務(wù)端误褪,則使用自身的憑證(self.credential)校驗(yàn),如果沒有憑證碾褂,則直接取消兽间;

4. 疑問

疑問:

  1. 當(dāng)下為什么很少使用雙向驗(yàn)證;主要是為了限制客戶端訪問正塌,白名單或與是個(gè)更好的解決方案嘀略?
  2. 為什么很少使用鎖定認(rèn)證?自簽名證書時(shí)使用更多乓诽,正規(guī)的 HTTPS 的話屎鳍,必要性不大了~~
  3. 中間人攻擊如何避免?HTTPS 下的 DH 算法问裕,中間人攻擊已經(jīng)很難了吧逮壁?三個(gè)隨機(jī)數(shù)、服務(wù)端和中間人公鑰不一致粮宛、最后雙端都會(huì)通過 finish 報(bào)文會(huì)對整個(gè)握手過程使用最終的對稱秘鑰進(jìn)行加密(簽名)并對比窥淆,基本沒辦法破解,所以 HTTPS 才成了互聯(lián)網(wǎng)基建一般的存在巍杈?忧饭??筷畦;

參考:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市鳖宾,隨后出現(xiàn)的幾起案子吼砂,更是在濱河造成了極大的恐慌,老刑警劉巖鼎文,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渔肩,死亡現(xiàn)場離奇詭異,居然都是意外死亡拇惋,警方通過查閱死者的電腦和手機(jī)周偎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來撑帖,“玉大人蓉坎,你說我怎么就攤上這事『伲” “怎么了蛉艾?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我伺通,道長,這世上最難降的妖魔是什么逢享? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任罐监,我火速辦了婚禮,結(jié)果婚禮上瞒爬,老公的妹妹穿的比我還像新娘弓柱。我一直安慰自己,他們只是感情好侧但,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布矢空。 她就那樣靜靜地躺著,像睡著了一般禀横。 火紅的嫁衣襯著肌膚如雪屁药。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天柏锄,我揣著相機(jī)與錄音酿箭,去河邊找鬼。 笑死趾娃,一個(gè)胖子當(dāng)著我的面吹牛缭嫡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播抬闷,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼妇蛀,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了笤成?” 一聲冷哼從身側(cè)響起评架,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎炕泳,沒想到半個(gè)月后古程,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡喊崖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年挣磨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荤懂。...
    茶點(diǎn)故事閱讀 40,872評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茁裙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出节仿,到底是詐尸還是另有隱情晤锥,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站矾瘾,受9級特大地震影響女轿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜壕翩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一蛉迹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧放妈,春花似錦北救、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宅倒,卻和暖如春攘宙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拐迁。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工模聋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人唠亚。 一個(gè)月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓链方,卻偏偏與公主長得像,于是被迫代替她去往敵國和親灶搜。 傳聞我的和親對象是個(gè)殘疾皇子祟蚀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評論 2 361

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