需求
“人們最初設計互聯網時,很少考慮到安全。這樣的結果是,核心通信協議本質上是不安全的,只能依靠所有參與方的誠信行為。互聯網在早期由少數節點(大部分是大學)構成,那時這也許行得通;但現在所有人都可以連接到互聯網,這種方式便土崩瓦解。”
因此要有一種加密方式在基于不安全的基礎設施提供安全通信。這種方式要能解決安全的三個核心要求:保持秘密(機密性)、驗證身份(真實性)、完整性(不會在傳輸過程中被篡改)
術語——HTTPS、SSL、TLS
SSL 是洋文“Secure Sockets Layer”的縮寫,中文叫做“安全套接層”。它是在上世紀90年代中期,由網景公司設計的。(順便插一句,網景公司不光發明了 SSL,還發明了很多 Web 的基礎設施——比如“CSS 樣式表”和“JS 腳本”)
為啥要發明 SSL 這個協議捏?因為原先互聯網上使用的 HTTP 協議是明文的,存在很多缺點——比如傳輸內容會被偷窺(嗅探)和篡改。發明 SSL 協議,就是為了解決這些問題。
到了1999年,SSL 因為應用廣泛,已經成為互聯網上的事實標準。IETF 就在那年把 SSL 標準化。標準化之后的名稱改為 TLS(是“Transport Layer Security”的縮寫),中文叫做“傳輸層安全協議”。
很多相關的文章都把這兩者并列稱呼(SSL/TLS),因為這兩者可以視作同一個東西的不同階段。
◇ “HTTPS”是啥意思?
解釋完 SSL/TLS,現在就可以來解釋 HTTPS 啦。咱們通常所說的 HTTPS 協議,說白了就是“HTTP 協議”和“SSL/TLS 協議”的組合。你可以把 HTTPS 大致理解為——“HTTP over SSL”或“HTTP over TLS”(反正 SSL 和 TLS 差不多)。
SSL成為標準之后的網絡通信的理論模型:開放系統互聯(open systems interconnection, OSI)模型
如下表格:
層號 | OSI層 | 描述 | 協議實例 |
---|---|---|---|
7 | 應用層 | 應用數據 | HTTP、SMTP、IMAP |
6 | 表示層 | 數據表示、轉換和加密 | SSL/TLS |
5 | 會話層 | 多連接管理 | - |
4 | 傳輸層 | 包或流的可靠傳輸 | TCP、UDP |
3 | 網絡層 | 網絡節點間的路由與數據分發 | IP、IPSec |
2 | 數據鏈路層 | 可靠的本地數據連接(LAN) | 以太網 |
1 | 物理層 | 直接物理數據連接(電纜) | CAT5 |
更簡單的圖示:
由上可知整個https的核心是SSL/TLS協議
SSL/TLS協議的握手過程
SSL/TLS協議的基本思路是采用公鑰加密法,也就是說,客戶端先向服務器端索要公鑰,然后用公鑰加密信息,服務器收到密文后,用自己的私鑰解密。
握手在實際操作中會遇到兩個問題:
(1)握手中服務器將公鑰發送給客戶端的時候如何保證公鑰不被篡改?
解決方法:將公鑰放在數字證書中。只要證書是可信的,公鑰就是可信的。
(2)公鑰加密計算量太大,如何減少耗用的時間?
解決方法:每一次對話(session),客戶端和服務器端都生成一個"對話密鑰"(session key),用它來加密信息。由于"對話密鑰"是對稱加密,所以運算速度非常快,而服務器公鑰只用于加密"對話密鑰"本身,這樣就減少了加密運算的消耗時間。
◇ SSL/TLS協議的基本過程
開始加密通信之前,客戶端和服務器首先必須建立連接和交換參數,這個過程叫做握手(handshake)。
假定客戶端叫做愛麗絲,服務器叫做鮑勃,整個握手過程分成五步:
第一步,愛麗絲給出協議版本號、一個客戶端生成的隨機數(Client random),以及客戶端支持的加密方法。
第二步,鮑勃確認雙方使用的加密方法,并給出數字證書、以及一個服務器生成的隨機數(Server random)。
第三步,愛麗絲確認數字證書有效,然后生成一個新的隨機數(Premaster secret),并使用數字證書中的公鑰,加密這個隨機數,發給鮑勃。
第四步,鮑勃使用自己的私鑰,獲取愛麗絲發來的隨機數(即Premaster secret)。
第五步,愛麗絲和鮑勃根據約定的加密方法,使用前面的三個隨機數,生成"對話密鑰"(session key),用來加密接下來的整個對話過程。
上面的五步,畫成一張圖,就是下面這樣。
再次強調:
1 為了數據安全的目的引入數據加密
2 公鑰加密法用來協商對稱加密的對話密鑰
3 協商前要將公鑰加密法的公鑰發送給客戶端,為了保證公鑰不被篡改、替換,需要證書的協助
所以服務關系為:證書->公鑰加密法公鑰發送->協商對稱加密的回話密鑰->數據傳輸加密
加密
◇ 啥是“加密”和“解密”?
通俗而言,你可以把“加密”和“解密”理解為某種【互逆的】數學運算。就好比“加法和減法”互為逆運算、“乘法和除法”互為逆運算。
“加密”的過程,就是把“明文”變成“密文”的過程;反之,“解密”的過程,就是把“密文”變為“明文”。在這兩個過程中,都需要一個關鍵的東東——叫做“密鑰”——來參與數學運算。
◇ 啥是“對稱加密”?
所謂的“對稱加密技術”,意思就是說:“加密”和“解密”使用【相同的】密鑰。這個比較好理解。就好比你用 7zip 或 WinRAR 創建一個帶密碼(口令)的加密壓縮包。當你下次要把這個壓縮文件解開的時候,你需要輸入【同樣的】密碼。在這個例子中,密碼/口令就如同剛才說的“密鑰”。
◇ 啥是“非對稱加密”?
所謂的“非對稱加密技術”,意思就是說:“加密”和“解密”使用【不同的】密鑰。想具體了解密鑰交換算法的同學可參考這篇文章:掃盲 HTTPS 和 SSL/TLS 協議[3]:密鑰交換(密鑰協商)算法及其原理
◇ 各自有啥優缺點?
看完剛才的定義,很顯然:(從功能角度而言)“非對稱加密”能干的事情比“對稱加密”要多。這是“非對稱加密”的優點。但是“非對稱加密”的實現,通常需要涉及到“復雜數學問題”。所以,“非對稱加密”的性能通常要差很多(相對于“對稱加密”而言)。
這兩者的優缺點,也影響到了 SSL 協議的設計。
◇ 加密方式可行性
★方案1——單純用“對稱加密算法”的可行性
首先簡單闡述一下,“單純用對稱加密”為啥是【不可行】滴。
如果“單純用對稱加密”,瀏覽器和網站之間勢必先要交換“對稱加密的密鑰”。
如果這個密鑰直接用【明文】傳輸,很容易就會被第三方(有可能是“攻擊者”)偷窺到;如果這個密鑰用密文傳輸,那就再次引入了“如何交換加密密鑰”的問題——這就變成“先有雞還是先有蛋”的循環邏輯了。
所以,【單純用】對稱加密,是沒戲滴。
★方案2——單純用“非對稱加密算法”的風險
說完“對稱加密”,再來說說“非對稱加密”。“加密和解密采用不同的密鑰”。基于這個特點,可以避開前面提到的“循環邏輯”的困境。大致的步驟如下:
第1步
網站服務器先基于“非對稱加密算法”,隨機生成一個“密鑰對”(為敘述方便,稱之為“k1 和 k2”)。因為是隨機生成的,目前為止,只有網站服務器才知道 k1 和 k2。第2步
網站把 k1 保留在自己手中,把 k2 用【明文】的方式發送給訪問者的瀏覽器。
因為 k2 是明文發送的,自然有可能被偷窺。不過不要緊。即使偷窺者拿到 k2,也【很難】根據 k2 推算出 k1
(這一點是由“非對稱加密算法”從數學上保證的)。第3步
瀏覽器拿到 k2 之后,先【隨機生成】第三個對稱加密的密鑰(簡稱 k)。
然后用 k2 加密 k,得到 k'(k' 是 k 的加密結果)
瀏覽器把 k' 發送給網站服務器。由于 k1 和 k2 是成對的,所以只有 k1 才能解密 k2 的加密結果。
因此這個過程中,即使被第三方偷窺,第三方也【無法】從 k' 解密得到 k第4步
網站服務器拿到 k' 之后,用 k1 進行解密,得到 k
至此,瀏覽器和網站服務器就完成了密鑰交換,雙方都知道 k,而且【貌似】第三方無法拿到 k
然后,雙方就可以用 k 來進行數據雙向傳輸的加密。
但是“方案2”依然是不安全滴——雖然“方案2”可以在一定程度上防止網絡數據的【偷窺/嗅探】,但是【無法】防范網絡數據的【篡改】。
假設有一個攻擊者處于“瀏覽器”和“網站服務器”的通訊線路之間,并且這個攻擊者具備“修改雙方傳輸數據”的能力。那么,這個攻擊者就可以攻破“方案2”。具體的攻擊過程如下:
第1步
這一步跟原先一樣——服務器先隨機生成一個“非對稱的密鑰對”k1 和 k2(此時只有網站知道 k1 和 k2)第2步
當網站發送 k2 給瀏覽器的時候,攻擊者截獲 k2,保留在自己手上。
然后攻擊者自己生成一個【偽造的】密鑰對(以下稱為 pk1 和 pk2)。
攻擊者把 pk2 發送給瀏覽器。第3步
瀏覽器收到 pk2,以為 pk2 就是網站發送的。
瀏覽器不知情,依舊隨機生成一個對稱加密的密鑰 k,然后用 pk2 加密 k,得到密文的 k'
瀏覽器把 k' 發送給網站。
(以下是關鍵)
發送的過程中,再次被攻擊者截獲。
因為 pk1 pk2 都是攻擊者自己生成的,所以攻擊者自然就可以用 pk1 來解密 k' 得到 k
然后,攻擊者拿到 k 之后,用之前截獲的 k2 重新加密,得到 k'',并把 k'' 發送給網站。第4步
網站服務器收到了 k'' 之后,用自己保存的 k1 可以正常解密,所以網站方面不會起疑心。
至此,攻擊者完成了一次漂亮的偷梁換柱,而且讓雙方都沒有起疑心。
上述過程,也就是傳說中大名鼎鼎的“中間人攻擊”。洋文叫做“Man-In-The-Middle attack”。縮寫是 MITM。
為了更加形象,補充兩張示意圖,分別對應“偷窺模式”和“中間人模式”。讓你更直觀地體會兩者的差異。
★方案2失敗的根源——缺乏【可靠的】身份認證
為啥“方案2”會失敗?
除了在圖中提到的“攻擊者具備篡改數據的能力”,還有另一點關鍵點——“方案2缺乏身份認證機制”。
正是因為“缺乏身份認證機制”,所以當攻擊者一開始截獲 k2 并把自己偽造的 pk2 發送給瀏覽器時,瀏覽器無法鑒別:自己收到的密鑰是不是真的來自于網站服務器。
假如具備某種【可靠的】身份認證機制,即使攻擊者能夠篡改數據,但是篡改之后的數據很容易被識破。那篡改也就失去了意義。
身份認證的幾種方式
下面,來介紹幾種常見的“身份認證原理”。
◇ 基于某些“私密的共享信息”
為了解釋“私密的共享信息”這個概念,咱們先拋開“信息安全”,談談日常生活中的某個場景。
假設你有一個久未聯系的老朋友。因為時間久遠,你已經沒有此人的聯系方式了。某天,此人突然給你發了一封電子郵件。
那么,你如何確保——發郵件的人確實是你的老朋友捏?
有一個辦法就是:你用郵件向對方詢問某個私密的事情(這個事情只有你和你的這個朋友知道,其他人不知道)。如果對方能夠回答出來,那么對方【很有可能】確實是你的老朋友。
從這個例子可以看出,如果通訊雙方具有某些“私密的共享信息”(只有雙方知道,第三方不知道),就能以此為基礎,進行身份認證,從而建立信任。
◇ 基于雙方都信任的“公證人”
“私密的共享信息”,通常需要雙方互相比較熟悉,才行得通。如果雙方本來就互不相識,如何進行身份認證以建立信任關系捏?
這時候還有另一個辦法——依靠雙方都信任的某個“公證人”來建立信任關系。
如今 C2C 模式的電子商務,其實用的就是這種方式——由電商平臺充當公證人,讓買家與賣家建立某種程度的信任關系。
考慮到如今的網購已經相當普及,大伙兒應該對這類模式很熟悉吧。所以俺就不浪費口水了。
◇ CA 的引入——如何解決 SSL 的身份認證問題
說完身份認證的方式/原理,再回到 SSL/TLS 的話題上。對于 SSL/TLS 的應用場景,由于雙方(“瀏覽器”和“網站服務器”)通常都是互不相識的,顯然不可能采用第一種方式(私密的共享信息),而只能采用第二種方式(依賴雙方都信任的“公證人”)。那么,誰來充當這個公證人捏?這時候,CA 就華麗地登場啦。所謂的 CA,就是“數字證書認證機構”的縮寫,洋文全稱叫做“Certificate Authority”。
服務端先從CA那里購買一個數字證書,證書里包含了服務端的公鑰。客戶端請求時將證書發給客戶端,客戶端驗證證書是否可信。如果可信就拿認為其中的公鑰是來自服務端的,可以使用。文章最后會詳細講解CA和CA證書
★基于 CA 證書進行密鑰交換
所謂的數字證書,技術上依賴的還是前面提到的“非對稱加密”。為了描述“CA 證書”在 SSL/TLS 中的作用,俺大致說一下原理(僅僅是原理,具體的技術實現要略復雜些)
第1步(這是“一次性”的準備工作)
網站方面首先要花一筆銀子,在某個 CA 那里購買一個數字證書。該證書通常會對應幾個文件:其中一個文件包含公鑰,還有一個文件包含私鑰。此處的“私鑰”,相當于“方案2”里面的 k1;而“公鑰”類似于“方案2”里面的 k2。網站方面必須在 Web 服務器上部署這兩個文件。所謂的“公鑰”,顧名思義就是可以公開的 key;而所謂的“私鑰”就是私密的 key。其實前面已經說過了,這里再嘮叨一下:“非對稱加密算法”從數學上確保了——即使你知道某個公鑰,也很難(不是不可能,是很難)根據此公鑰推導出對應的私鑰。
第2步
當瀏覽器訪問該網站,Web 服務器首先把包含公鑰的證書發送給瀏覽器。
第3步
瀏覽器驗證網站發過來的證書。如果發現其中有詐,瀏覽器會提示“CA 證書安全警告”。由于有了這一步,就大大降低了(注意:是“大大降低”,而不是“徹底消除”)前面提到的“中間人攻擊”的風險。為啥瀏覽器能發現 CA 證書是否有詐?因為正經的 CA 證書,都是來自某個權威的 CA。如果某個 CA 足夠權威,那么主流的操作系統(或瀏覽器)會內置該 CA 的“根證書”。(比如 Windows 中就內置了幾十個權威 CA 的根證書)因此,瀏覽器就可以利用系統內置的根證書,來判斷網站發過來的 CA 證書是不是某個 CA 頒發的。(關于“根證書”和“證書信任鏈”的概念,請參見之前的教程《數字證書及CA的掃盲介紹》)
第4步
如果網站發過來的 CA 證書沒有問題,那么瀏覽器就從該 CA 證書中提取出“公鑰”。然后瀏覽器隨機生成一個“對稱加密的密鑰”(以下稱為 k)。用 CA 證書的公鑰加密 k,得到密文 k'瀏覽器把 k' 發送給網站。
第5步
網站收到瀏覽器發過來的 k',用服務器上的私鑰進行解密,得到 k。至此,瀏覽器和網站都擁有 k,“密鑰交換”大功告成啦。
至此終于將公鑰安全送達瀏覽器手中,完成了身份認證。
數字簽名和CA
◇ 數字簽名
數字簽名是使用非對稱加密來確保消息或其他數據的完整性的一種方式。簽名人必須有一個數字身份包括:一對公私鑰和相應的證明簽名者公鑰真實性的數字證書。
簽名者首先計算文件摘要(例如Hash函數)然后私鑰加密摘要,生成簽名。將簽名附在加密的文件中發送給收件人,將解密的公鑰放到證書中也發送給收件人。
收件人用相同的算法計算文件摘要,然后用證書中的公鑰解密加密的摘要,如果兩個摘要相同則證明消息并沒有被更改并且由密鑰的所有者發送。
創建數字簽名:
驗證數字簽名:
這里有個問題就是如果文件被中間人更改,用自己的私鑰簽名,然后同時替換了簽名和證書,收件人用中間人發送來的公鑰解密中間人對文件的簽名,依然可以驗證通過,但是文件已經被更改了啊。
因此為了證明簽名提供者就是他聲明的那個人(不是中間人冒充的),證書也需要被簽名,此類證書也由簽發證書的認證機構簽字。
也即是說證書提供的身份認證機制依賴于數字簽名。證書的數字簽名確保證書不能夠被中間人更改。
◇ CA對數字證書簽名
★數字證書
數字證書是用于驗證證書的持有人或發件人身份的數據集合。
例如,X.509證書包含以下信息:
結構信息版本,序列號,用于創建簽名的消息摘要算法等等
來自證書頒發機構(CA)的數字簽名 - 頒發證書的個人或組織 - 以確保證書未被更改,并指示發行人(CA)的身份
有關證書持有人姓名,電子郵件地址,公司名稱,所有者公鑰等的信息
有效期(證書在此期間之前或之后無效)
-
證書擴展 -包含其他信息的屬性,例如此證書的允許用途
image.png
每個證書都是由另一個證書簽名的,由此產生了一個證書信任鏈,鏈中的每個證書都由下一個證書進行數字簽名,直到根證書,根證書的所有者成為根證書頒發機構
根證書是自簽名的,意思是根證書的簽名是由根證書頒發機構自己創建使用自己的私鑰簽名。
根證書頒發機構創建自己的證書然后創建中間證書頒發機構的證書
★ 證書的創建
根證書:
- 根證書頒發機構首先創建一對公私鑰
- 創建證書,先將公鑰填進證書,然后計算證書摘要,用私鑰加密摘要生成簽名,并將簽名附到證書中。 根證書創建完成
根證書頒發機構創建中間證書頒發機構的證書:
- 中間頒發機構生成自己的一對公私鑰
- 創建證書,將公鑰填進證書,將證書發送給根證書頒發機構申請簽名
- 根證書頒發機構計算中間頒發機構發來證書的摘要,用自己的私鑰加密摘要生成簽名,并將簽名附到證書中
- 根證書頒發機構還在該證書中填寫了自己的機構信息以聲明這張證書是我簽名的,以后需要驗證這張證書的真偽的時候需要用到我的證書
最終用戶證書的生成需要中間證書頒發機構簽名,流程和中間證書的生成類似。
用戶使用最終用戶證書給文檔簽名,用戶服務端用私鑰對文檔簽名,公鑰在證書中,證書發給用戶客戶端,客戶端用先驗證證書的真實性,然后用證書中的公鑰解密摘要驗證文檔的完整性。
★證書的驗證
客戶端拿到證書以后使用證書中的公鑰之前,要驗證證書的真實性
證書的驗證過程就是沿著證書創建過程中產生的證書鏈回溯到根證書的過程
- 根據證書中包含的簽名頒發機構信息獲取上一級的證書,獲取整個證書鏈
- 根證書的公鑰解密中間證書中的簽名得到摘要s,計算中間證書的摘要t,對比s和t,如果一致中間證書可信,否則不可信,驗證通不過
- 中間證書驗證通過后,用中間證書中的公鑰解密最終用戶證書的簽名得到摘要k,計算最終用戶的摘要m,對比k和m,如果一致則最終用戶證書可信,否則驗證通不過
上邊驗證了中間證書和最終用戶證書的真實性,但是根證書呢?還沒驗證根證書的真實性呢,根證書是自簽名的,用根證書中的公鑰永遠能解開他自己的簽名,怎么驗證?
從算法邏輯上沒法驗證根證書的真實性了。
實際上,根證書是靠操作系統驗證真實性的。操作系統中維護了一個證書列表,各大CA機構的根證書都在其中,表示操作系統信任這個列表中的所有證書(點擊查看iOS or macOS信任的根證書列表),證書驗證的時候會查看根證書是否在系統信任更證書列表里,如果在,根證書就可信任,然后驗證中間證書和最終用戶證書。
系統信任根證書列表是會變動的:新的CA達到系統信任級別或者已存在的CA變得不可信任。
關于證書這一塊,個人理解感覺也有偏差,可以查看大神寫的數字證書及 CA 的掃盲介紹
總結
終于對https有了大體的了解
本文大量引(抄)用(襲)了掃盲 HTTPS 和 SSL/TLS 協議[0]:引子列出文章的內容,通過這個引子里的相關文章,才算對https有了體會。深表感謝。雖然大量抄襲并且改動了一些導致沒有原文講的好,有興趣的同學可以直接去閱讀原文,我只是想把不明白的地方搞明白然后做個記錄。
下篇筆記iOS開發中對https的處理開始學習一下NSURLSession中對https的處理.
參考:
掃盲 HTTPS 和 SSL/TLS 協議[0]:引子
圖解SSL/TLS協議
SSL/TLS協議運行機制的概述
《HTTPS權威指南》
Cryptography Concepts In Depth