由《HTTPS權威指南》- SSL、TLS和密碼學學習筆記知道了協議的用處,這裏再貼一遍:javascript
加密基元自己沒有什麼用,例如加密和散列算法。咱們只有將這些元素組合成方案和協議才能知足複雜的安全需求。java
實例場景:
Alice和Bob要通訊。Mallory是個攻擊者。算法
咱們假設協議容許交換任意數量的消息。由於對稱加密擅長對大量數據進行加密,因此選取咱們最喜歡的AES算法來進行數據加密。使用AES,Alice和Bob能夠安全的交換消息,Malloc看不到他們通訊的內容。可是這還不夠,由於Malloc還能夠幹其它事情,例如神不知鬼不覺的修改消息。爲了解決這個問題,咱們使用只有Alice和Bob知道的散列密鑰計算每一個消息的MAC,在發送消息的同時,也發送消息的MAC。這時Mallory不再能修改消息了,然而他仍然能夠丟棄或者重發任意消息。爲了解決這個問題,咱們擴展協議,爲每條消息標記指定序號。最爲重要的是,咱們將序號做爲MAC計算數據的一部分。若是發現序號出現空缺,就能知道消息丟了。若是發現序號重複,就檢測重放攻擊。爲了獲得最佳效果,咱們使用某個特殊消息來標記會話結束。若是沒有這個消息,Mallory可以悄悄的結束(截斷)會話。若是全部措施以到位,Mallory最多隻能作到阻止Alice和Bob與其餘人通訊。咱們對此無能爲力。緩存
到目前爲止,有一大塊缺失:Alice和Bob如何協商獲得須要的兩個密鑰(一個用於加密(AES的密鑰),一個用於檢測完整性(MAC的密鑰)),同時還要小心Mallory?咱們經過爲協議添加兩個步驟來解決這個問題:
使用公鑰密碼對會話進行身份驗證。舉個例子,Alice生成一個隨機數,要求Bob對其簽名以證實真的是他,Bob也要求Alice作一樣的事情。
使用密鑰交換方案對加密密鑰進行祕密協商。舉個例子,Alice能夠生成全部密鑰,使用Bob的公鑰加密,再發送給Bob,這就是RSA密鑰交換的工做方式。安全
最後咱們協議完工時的狀態是:
以握手階段開始,包括身份驗證和密鑰交換
數據交換階段,保存機密性和完整性
以關閉序列結束。服務器
站在宏觀的角度看,咱們的協議與SSL和TLS完成的工做類似。網絡
這篇文章將描述TLS協議中的具體體現。session
宏觀上TLS以記錄協議(record protocol)實現。併發
TLS協議須要哪些加密基元?
握手過程當中:app
傳輸過程當中:
以上基元和其它參數構成了密碼套件,它能夠精肯定義如何實現安全,密碼套件都傾向於使用較長的描述性名稱,而且至關一致:
TLS_密鑰交換_身份驗證_WITH_密碼_完整性保證複製代碼
其中密碼可寫爲:
算法_強度_模式複製代碼
所以密碼套件與下所示:
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256複製代碼
表示:
以RSA公鑰驗證身份,使用ECDHE密鑰交換,使用AES_128_GCM加密傳輸的數據,使用SHA256保證數據完整性。
在握手協議完成前,消息傳輸沒有收到任何保護(從技術上講,就是使用了TLS_NULL_WITH_NULL_NULL密碼套件),一旦握手完成,就開始按協商取得的鏈接參數進行加密和完整性驗證。
由上能夠握手協議的目的有:
在TLS中,會話安全性取決於成爲主密鑰(master secret)的48字節共享密鑰。密鑰交換的目的是計算另外一個值,即預主密鑰(premaster secret),這個值是組成主密鑰的來源。
TLS支持許多密鑰交換算法,好比下表所示:
密鑰交換 | 描述 |
---|---|
dh_anon | Diffie-Hellman(DH)密鑰交換,未經身份驗證 |
dhe_rsa | 臨時DH密鑰交換,使用RSA身份驗證 |
ecdh_anon | 臨時橢圓曲線DH(elliptic curve DH,ECDH)密鑰交換,未經身份驗證 |
ecdhe_rsa | 臨時ECDH密鑰交換,使用RSA身份驗證 |
ecdhe_ecdsa | 臨時ECDH密鑰交換,使用RSA身份驗證 |
使用哪種密鑰交換是由協商的套件所決定。一旦套件決定下來,兩端都能瞭解按照哪一種算法繼續操做。
RSA密鑰交換
交換方式:客戶端生成預主密鑰,使用服務器公鑰對其加密,將其包含在ClientKeyExchange消息中,最後發送出去。服務器只須要使用私鑰解密這條消息就能獲得預主密鑰。
攻擊方式:對手能夠制定長期行動,攻擊者會記錄全部加密的流量,耐心等待有朝一日能夠獲得密鑰。好比,計算機能力的進步使暴力破解成爲可能,也能夠經過法律強制力、政治高壓、賄賂或強行進入使用該密鑰的服務器來取得密鑰。只要密鑰泄露,就能夠解密以前的全部流量了。(由於從私鑰能夠很容易推出預主密鑰,而後推出主密鑰。)
Diffie-Hellman密鑰交換
是一種密鑰協定的協議,支持前向保密,訣竅是正向計算簡單,逆向計算困難的數學函數,即便交換中的某些因子已被知曉,狀況也是同樣。最恰當的類比示例是混色:若是有兩種顏色,那麼狠容易將其混在一塊兒獲得第三種顏色,可是若是隻有第三種顏色,很難肯定到底是哪兩種顏色混合而成。
實現:DH密鑰交換須要6個參數:其中兩個(dh_p,dh_g)稱爲域參數,由服務器選定,協商過程當中,客戶端和服務器各自生成另外兩個參數,相互發送其中一個參數(dh_Ys和dh_Yc)到對端,在通過計算,最終獲得共享密鑰。
單向驗證
如下圖片來自:SSL/TLS 握手過程詳解
一、客戶端開始新的握手(ClientHello),
二、服務器選擇鏈接參數,並返回一個隨機數(ServerHello)
三、服務器發送證書鏈(Certificate)
四、根據鏈接參數中的密鑰交換方式,發送生產主密鑰的額外信息。(ServerKeyExchange)
五、服務器通知本身完成了協商過程。(ServerHelloDone)
//主密鑰生成函數PRF
master_seret = PRF(pre_master_secret,"master secret", ClientHello.random+ServerHello.random)複製代碼
7:客戶端切換加密方式並通知服務器(change clipeher spec:告訴服務器,我下面發的信息都要加密了)。
8:客戶端計算髮送和接收到的握手消息的MAC併發送(finished:客戶端發送第一條加密信息)。
9:服務器切換加密方式並通知客戶端(change clipher spec:告訴客戶端,我下面發的信息都要加密了)。
10:服務器計算髮送和接收到的握手信息的MAC併發送(finished:服務器發送第一條加密信息)。
由上面能夠看出,第一、2步Hello消息是用來協商取得鏈接,3-6步是用來驗證身份和交換密鑰,最後8和10步須要MAC是用來驗證握手消息沒被第三方修改。
以上握手流程圖示:
雙向驗證
只有已經通過身份驗證的服務器才容許請求客戶端身份驗證。
與單向驗證添加如下步驟:
一、服務器發送CertificateRequest消息請求客戶端進行身份驗證,消息中帶有接受的證書的公鑰和簽名算法或者證書頒發機構列表。
二、客戶端發送證書鏈給服務器Certificate。
三、客戶端使用CertificateVerify消息證實本身擁有的私鑰與以前發送的客戶端證書中的公鑰相對應。
圖示以下:
會話恢復
完整的握手協議很是複雜,須要不少握手消息和兩次網絡往返才能開始發送客戶端應用數據。此外握手執行的密鑰學操做一般須要密集的CPU處理。身份驗證一般以客戶端和服務器的證書驗證來完成,須要更多的工做。這其中許多消耗均可以經過簡短的握手方式節約下來。
最初的會話機制是再一次完整協商的鏈接斷開時,客戶端和服務器都會將會話的安全參數保存一段時間。
步驟:
這樣的結果是握手只須要一次網絡往還。
圖示:
用來替代服務器會話緩存與恢復的方案:
會話票證(session ticker):除了全部的狀態都保存在客戶端(與HTTPCookie原理相似)以外,其消息流與服務器會話緩存一致
記錄層使用當前鏈接安全參數對這些信息進行打包、碎片整理和加密。
以簡單的方式告知對端通訊出現異常,一般會攜帶close_notify異常,在鏈接關閉時使用。
關閉鏈接警報用以有序的方式關閉TLS鏈接。
步驟:
能夠避免截斷攻擊,由於沒有關閉協議,通訊雙方沒法確認是遭受攻擊仍是通訊結束。
個人簡書主頁:www.jianshu.com/users/b92ab…