HTTPS協(xié)議
前言
HTTPS協(xié)議
加密方式:
數字證書:
HTTPS的驗證過程
重放與篡改:
前言
上一篇記錄了一下HTTP協(xié)議以及基于UDP協(xié)議實現的可靠傳輸協(xié)議QUIC協(xié)議。
眾所周知,HTTP協(xié)議是直接進行明文傳輸的,交互過程以及數據傳輸都沒有進行加密,通信雙方也沒有進行任何認證,因此通信過程非常容易遭遇劫持、監(jiān)聽、篡改。嚴重情況下,會造成惡意的流量劫持。
所以在復雜的網絡環(huán)境中,急需一個傳輸安全的協(xié)議,于是HTTPS協(xié)議就產生了。
HTTPS協(xié)議
加密方式:
(1)對稱加密
加密解密使用相同的密鑰
(2)非對稱加密
加解密使用過的密鑰不同,一個是公開的公鑰,一個是私有的私鑰,公鑰加密的信息,只要私鑰才能解密,私鑰加密的信息,只有公鑰才能解密。
客戶端發(fā)送,使用服務端公鑰加密,服務端發(fā)送,使用客戶端公鑰加密。
數字證書:
證書由權威機構CA發(fā)布,證書里有公鑰、證書所有者、證書發(fā)布機構和證書有效期。
CA會用一個簽名算法給證書簽名,用只掌握在權威機構手里的東西簽名了才行,這就是CA的私鑰。
下圖是微信公眾號網站的證書:

簽名算法:
對信息做一個 Hash 計算,得到一個 Hash 值,這個過程是不可逆的,也就是說無法通過 Hash 值得出原來的信息內容。在把信息發(fā)送出去時,把這個 Hash 值加密后,作為一個簽名和信息一起發(fā)出去
此時請求會得到一個證書,證書有個發(fā)布機構CA,只要獲取此CA的公鑰,去解密證書的簽名,解密成功并Hash也對的上,就說明這個公鑰沒有問題。
請求的時候將證書(證書也是通過CA私鑰加密的)發(fā)給服務端,服務端獲取到相應機構的公鑰,用來解密證書,解密后,校驗Hash值,如果校驗成功,說明公鑰沒問題,此時就會獲取到客戶端的公鑰。
如何確定CA的公鑰就是正確的?
CA 的公鑰也需要更牛的 CA 給它簽名,然后形成 CA 的證書。
要想知道某個 CA 的證書是否可靠,要看 CA 的上級證書的公鑰,能不能解開這個 CA 的簽名。
這樣層層上去,直到全球皆知的幾個著名大 CA,稱為 root CA,做最后的背書。
通過這種層層授信背書的方式,從而保證了非對稱加密模式的正常運轉。
HTTPS的驗證過程

https 通信分為四個步驟:
c->s,客戶端發(fā)起加密通信請求,這個請求通常叫做 ClientHello請求,告知自己支持的協(xié)議版本號,加密算法,壓縮算法,以及一個用于生成后續(xù)通信密鑰的隨機數;
s->c,服務端響應,也叫作 ServerHello,確認加密通信協(xié)議,加密算法,以及一個用于生成后續(xù)通信密鑰的隨機數,還有網站證書;
c->s,客戶端在收到上一步服務端的響應之后,首先會檢查證書的頒發(fā)者是否可信任,是否過期,域名是否一致,并且從操作系統(tǒng)的證書鏈中找出該證書的上一級證書,并拿出服務端證書的公鑰,然后驗證簽名和hash,如果驗證失敗,就會顯示警告,會在瀏覽器看到,“此網站有風險,是否繼續(xù)什么的”。如果驗證通過,客戶端會向服務端發(fā)送一個稱作 “pre-master-key” 的隨機數,該隨機數使用證書的公鑰加密,以及編碼改變通知(以后咋們就用協(xié)商的密鑰堆成加密通信了),客戶端完成握手。
服務端在收到上一步客戶端請求之后,也會確認以后發(fā)給客戶端的信息都是加密的,并且完成握手。
此時,客戶端有第一步自己生成的隨機數,第二步收到服務端的隨機數,第三步的 pre-master-key,服務端也是如此,他們就可以用這三個隨機數使用約定的算法生成同一個密鑰來加密以后的通信數據了。
重放與篡改:
有了加密和解密,黑客截獲了包也打不開了,但是它可以發(fā)送 N 次。
這個往往通過 Timestamp 和 Nonce 隨機數聯合起來,然后做一個不可逆的簽名來保證。
Nonce 隨機數保證唯一,或者 Timestamp 和 Nonce 合起來保證唯一,同樣的,請求只接受一次,于是服務器多次收到相同的 Timestamp 和 Nonce,則視為無效即可。
如果有人想篡改 Timestamp 和 Nonce,還有簽名保證不可篡改性,如果改了用簽名算法解出來,就對不上了,可以丟棄了。
Nonce是由服務器生成的一個隨機數,在客戶端第一次請求頁面時將其發(fā)回客戶端;客戶端拿到這個Nonce,將其與用戶密碼串聯在一起并進行非可逆加密(MD5、SHA1等等),然后將這個加密后的字符串和用戶名、Nonce、加密算法名稱一起發(fā)回服務器;服務器使用接收到的用戶名到數據庫搜索密碼,然后跟客戶端使用同樣的算法對其進行加密,接著將其與客戶端提交上來的加密字符串進行比較,如果兩個字符串一致就表示用戶身份有效。這樣就解決了用戶密碼明文被竊取的問題,攻擊者就算知道了算法名和nonce也無法解密出密碼。
每個nonce只能供一個用戶使用一次,這樣就可以防止攻擊者使用重放攻擊,因為該Http報文已經無效??蛇x的實現方式是把每一次請求的Nonce保存到數據庫,客戶端再一次提交請求時將請求頭中得Nonce與數據庫中得數據作比較,如果已存在該Nonce,則證明該請求有可能是惡意的。然而這種解決方案也有個問題,很有可能在兩次正常的資源請求中,產生的隨機數是一樣的,這樣就造成正常的請求也被當成了攻擊,隨著數據庫中保存的隨機數不斷增多,這個問題就會變得很明顯。所以,還需要加上另外一個參數Timestamp(時間戳)。
Timestamp是根據服務器當前時間生成的一個字符串,與nonce放在一起,可以表示服務器在某個時間點生成的隨機數。這樣就算生成的隨機數相同,但因為它們生成的時間點不一樣,所以也算有效的隨機數
