前言
大家都知道,蘋果在2016年WWDC上宣佈了關於應用需要強制使用HTTPS
的規定。這也算是個好訊息吧,雖然開發者們可能需要適配下HTTPS
,但是我們的應用可算是披上一個安全的保護罩了。本篇文章就算是筆者在學習HTTPS
過程中的一個記錄吧。
HTTPS加密過程
最近重新瞭解了下HTTP
和HTTPS
: 首先二者都是網路傳輸協議;HTTPS
在傳輸過程中是可以通過加密來保護資料安全的,以免使用者敏感資訊被第三方獲取。 可以說HTTPS
是HTTP
的升級版、安全版。下面我們就簡單看下HTTPS的加密過程,先看下圖。
- 客戶端發起
HTTPS
請求
這個沒什麼好說的,就是使用者在瀏覽器裡輸入一個HTTPS
網址,然後連線到服務端的443埠。 - 服務端的配置
採用HTTPS
協議的伺服器必須要有一套數字證書,可以自己製作,也可以向組織申請。區別就是自己頒發的證書需要客戶端驗證通過,才可以繼續訪問,而使用受信任的公司申請的證書則不會彈出提示頁面。這套證書其實就是一對公鑰和私鑰。如果對公鑰不太理解,可以想象成一把鑰匙和一個鎖頭,只是世界上只有你一個人有這把鑰匙,你可以把鎖頭給別人,別人可以用這個鎖把重要的東西鎖起來,然後發給你,因為只有你一個人有這把鑰匙,所以只有你才能看到被這把鎖鎖起來的東西。 - 傳送證書
這個證書其實就是公鑰,只是包含了很多資訊,如證書的頒發機構,過期時間等等。 - 客戶端解析證書
這部分工作是由客戶端的SSL/TLS來完成的,首先會驗證公鑰是否有效,比如頒發機構,過期時間等等,如果發現異常,則會彈出一個警示框,提示證書存在的問題。如果證書沒有問題,那麼就生成一個***隨機值***。然後用證書(也就是公鑰)對這個隨機值進行加密。就好像上面說的,把隨機值用鎖頭鎖起來,這樣除非有鑰匙,不然看不到被鎖住的內容。 - 傳送加密資訊
這部分傳送的是用證書加密後的隨機值,目的是讓服務端得到這個隨機值,以後客戶端和服務端的通訊就可以通過這個隨機值來進行加密解密了。 - 服務端解密資訊
服務端用私鑰解密後,得到了客戶端傳過來的隨機值,然後把內容通過該隨機值進行對稱加密,將資訊和私鑰通過某種演算法混合在一起,這樣除非知道私鑰,不然無法獲取內容,而正好客戶端和服務端都知道這個私鑰,所以只要加密演算法夠彪悍,私鑰夠複雜,資料就夠安全。 - 傳輸加密後的資訊
這部分資訊就是服務端用私鑰加密後的資訊,可以在客戶端用隨機值解密還原。 - 客戶端解密資訊
客戶端用之前生產的私鑰解密服務端傳過來的資訊,於是獲取瞭解密後的內容。整個過程第三方即使監聽到了資料,也束手無策。
到了這裡,HTTPS
的整個加密過程也就差不多完成了,但是這個過程中是不是還有些概念還是不太清楚,比如SSL
是什麼,TLS
又是什麼,他們是怎麼驗證我們的證書是否有效的呢,它們的驗證策略又是怎樣的呢。別急,下面我們就討論下TLS
。
TLS
剛開始聽到TLS
的時候,你可能還不太熟悉,但是說起SSL
你可能就覺得好耳熟了。其實TLS
就是從SSL
發展而來的,只是SSL
發展到3.0版本後改成了TLS
。
TLS
主要提供三個基本服務
- 加密
- 身份驗證,也可以叫證書驗證吧~
- 訊息完整性校驗
第三個是網路協議中常用的一個校驗和機制,我這我們就先按下不表。
加密
我們再看一遍客戶端和服務端之間的加密機制:
TLS
協議是基於TCP
協議之上的,圖中第一個藍色往返是TCP
的握手過程,之後兩次橙色的往返,我們可以叫做TLS
的握手。握手過程如下:
client1
:TLS
版本號+所支援加密套件列表+希望使用的TLS
選項Server1
:選擇一個客戶端的加密套件+自己的公鑰+自己的證書+希望使用的TLS
選項+(要求客戶端證書);Client2
:(自己的證書)+使用伺服器公鑰和協商的加密套件加密一個對稱祕鑰(自己生成的一個隨機值);Server2
:使用私鑰解密出對稱祕鑰(隨機值)後,傳送加密的Finish訊息,表明完成握手
這裡可能要提一下什麼是對稱加密和非對稱加密:
一般的對稱加密像這樣:
encrypt(明文,祕鑰) = 密文
decrypt(密文,祕鑰) = 明文
複製程式碼
也就是說加密和解密用的是同一個祕鑰。而非對稱加密是這樣的:
encrypt(明文,公鑰) = 密文
decrypt(密文,私鑰) = 明文
複製程式碼
加密和解密是需要不同的祕鑰的。
經過這幾次握手成功後,客服端和服務端之間通訊的加密演算法和所需要的金鑰也就確定下來了,之後雙方的互動都可以使用對稱加密演算法加密了。
證書機制/證書驗證
在TLS
中,我們需要證書來保證你所訪問的伺服器是真實的,可信的。
看這張圖我們來討論下證書的驗證過程。
- 客戶端獲取到了站點證書,拿到了站點的公鑰;
- 要驗證站點可信後,才能使用其公鑰,因此客戶端找到其站點證書頒發者的資訊;
- 站點證書的頒發者驗證了服務端站點是可信的,但客戶端依然不清楚該頒發者是否可信;
- 再往上回溯,找到了認證了中間證書商的源頭證書頒發者。由於源頭的證書頒發者非常少,我們瀏覽器之前就認識了,因此可以認為根證書頒發者是可信的;
- 一路倒推,證書頒發者可信,那麼它所頒發的所有站點也是可信的,最終確定了我們所訪問的服務端是可信的;
- 客戶端使用證書中的公鑰,繼續完成
TLS
的握手過程。
那麼,客戶端是是如何驗證某個證書的有效性,或者驗證策略是怎樣的?
證書頒發者一般提供兩種方式來驗證證書的有效性: CRL 和 OCSP。
CRL
CRL(Certificate Revocation List)
即 證書撤銷名單。證書頒發者會提供一份已經失效證書的名單,供瀏覽器驗證證書使用。當然這份名單是巨長無比的,瀏覽器不可能每次TLS都去下載,所以常用的做法是瀏覽器會快取這份名單,定期做後臺更新。這樣雖然後臺更新存在時間間隔,證書失效不實時,但一般也OK。
OCSP
OCSP(Online Certificate StatusProtocol)
即 線上證書狀態協議。除了離線檔案,證書頒發者也會提供實時的查詢介面,查詢某個特定證書目前是否有效。實時查詢的問題在於瀏覽器需要等待這個查詢結束才能繼續TLS握手,延遲會更大。
以上是站點在證書頒發者的角度說明會提供的兩種判斷方式,實際情況下瀏覽器究竟會選擇哪種方式判斷,每個瀏覽器都會有自己的實現。下面是通過Chrome檢視GitHub網站的證書資訊:
到這裡差不多了,有什麼不對的地方,歡迎大家留言指出,一起學習進步!
筆者不才,有些地方還是理解不到位,若有不正之處,還請耐心指出,輕噴~。
參看文章