轉自https://www.jianshu.com/p/a3a25c6627ee
https://blog.csdn.net/xingtian713/article/details/11953057
https://blog.csdn.net/caofengtao1314/article/details/87912078
TCP、Https、SSL/TLS、https的關系
-
TCP
傳輸控制協議,屬於傳輸層協議,提供可靠數據傳輸。它為http等應用層協議提供服務。 -
Http
超文本傳輸協議,屬於應用層協議。依賴於TCP協議。 -
SSL/TLS
安全傳輸層協議,用於在兩個通信應用程序之間提供保密性和數據完整性。位於某個可靠的傳輸協議(例如 TCP)上面,屬於應用層協議。 -
Https
在Http和TCP中間加入了SSL/TLS,保證數據傳輸的安全性
Https理論
在說HTTPS之前先說說什么是HTTP,HTTP就是我們平時瀏覽網頁時候使用的一種協議。HTTP協議傳輸的數據都是未加密的,也就是明文的,因此使用HTTP協議傳輸隱私信息非常不安全。
為了保證這些隱私數據能加密傳輸,於是網景公司設計了SSL(Secure Sockets Layer)協議用於對HTTP協議傳輸的數據進行加密,從而就誕生了HTTPS。SSL目前的版本是3.0,被IETF(Internet Engineering Task Force)定義在RFC 6101中。。
之后IETF對SSL 3.0進行了升級,於是出現了TLS(Transport Layer Security) 1.0,定義在RFC 2246。實際上我們現在的HTTPS都是用的TLS協議,但是由於SSL出現的時間比較早,並且依舊被現在瀏覽器所支持,因此SSL依然是HTTPS的代名詞,但無論是TLS還是SSL都是上個世紀的事情,SSL最后一個版本是3.0,今后TLS將會繼承SSL優良血統繼續為我們進行加密服務。目前TLS的版本是1.2。
Https的工作原理
HTTPS在傳輸數據之前需要客戶端(瀏覽器)與服務端(網站)之間進行一次握手,在握手過程中將確立雙方加密傳輸數據的密碼信息。TLS/SSL協議不僅僅是一套加密傳輸的協議,更是一件經過藝術家精心設計的藝術品,TLS/SSL中使用了非對稱加密,對稱加密以及HASH算法。
- 瀏覽器把自身支持的一系列Cipher Suite(密鑰算法套件,后文簡稱Cipher)[C1,C2,C3, …]發給服務器;
- 服務器接收到瀏覽器的所有Cipher后,與自己支持的套件作對比,如果找到雙方都支持的Cipher,則告知瀏覽器;
1、瀏覽器
瀏覽器支持哪些Cipher?這取決於瀏覽器支持的SSL/TLS協議的版本。習慣上,我們通常把HTTPS與SSL協議放到一起;事實上,SSL協議是Netcape公司於上世紀90年代中期提出的協議,自身發展到3.0版本。1999年該協議由ITEL接管,進行了標准化,改名為TLS。可以說,TLS 1.0就是SSL 3.1版本。在Wikipedia上並沒有SSL獨立的條目,而是會重定向到TLS,可見兩種協議關系之緊密。
目前TLS最新版本是1.2。互聯網上有超過99%的網站支持TLS 1.0,而支持TLS 1.2的網站尚不足40%。打開Firefox瀏覽器,在地址欄中輸入about:config,然后搜索tls.version,會看到下面的選項:
其中security.tls.version.min和security.tls.version.max兩項決定了Firefox支持的SSL/TLS版本,根據Firefox文檔的介紹,這兩項的可選值及其代表的協議是:
- 0 – SSL 3.0
- 1 – TLS 1.0
- 2 – TLS 1.1
- 3 – TLS 1.2
- 4 _ TLS 1.3
security.tls.version.min 改為4 的時候,意味着只支持TLS1.3 ,這是訪問不支持該版本的網站 例如:https://www.amazon.com/ 訪問會失敗 (如截圖)
簡易握手過程示例如下


第一步 Client Hello
先看一下抓出來包的內容,我們直接看到SSL層
這一步干啥了呢?
- TLS的版本
- 隨機數:這個是用來生成最后加密密鑰的影響因子之一,包含兩部分:時間戳(4-Bytes)和隨機數(28-Bytes) 這個隨機數,很重要。我們先記為Random1。
- session-id:用來表明一次會話,第一次建立沒有。如果以前建立過,可以直接帶過去。后面的擴展內容會詳細講到。
- 加密算法套裝列表:客戶端支持的加密-簽名算法的列表,讓服務器去選擇。
- 壓縮算法:似乎一般都不用
- 擴展字段:比如密碼交換算法的參數、請求主機的名字等等

看一下第4點加密算法套裝列表:客戶端支持的加密-簽名算法的列表有哪些
第二步 Server Hello (本例抓包占用了85字節,1360-85=剩余的1275字節為 被分段的Certificate部分)
包含三部分內容
- 據客戶端支持的SSL/TLS協議版本,確定使用的SSL/TLS協議版本
- 確定加密套件,壓縮算法
- 產生了一個隨機數Random2。注意,至此客戶端和服務端都擁有了兩個隨機數(Random1+ Random2),這兩個隨機數會在后續生成對稱秘鑰時用到
-
Server Hello 包wireshark解析
- 1、據客戶端支持的SSL/TLS協議版本,和自己的比較確定使用的SSL/TLS協議版本
-
2、確定加密套件,壓縮算法
3、產生了一個隨機數Random2。注意,至此客戶端和服務端都擁有了兩個隨機數(Random1+ Random2),這兩個隨機數會在后續生成對稱秘鑰時用到
第三步 Certificate Server Key Exchange ServerHello Done(Server => Client)
這次傳輸包含三部分內容
- Certificate 本例抓包由第6、7、9 個包組成;每個包分別含有該證書的字節數分別為1275、1360、4 字節,共計2639字節。這里主要就是把證書發送給Client。圖中可以看到我的證書和證書發放機構。客戶端拿到證書后就可以進行驗證,同時獲取到公鑰,用於后面Random3的加密。
- Server Key Exchange 這個消息是用來發送密鑰交換算法相關參數和數據的。這里要提前提一下,就是根據密鑰交換算法的不同,傳遞的參數也是不同的。
常用的密鑰交換算法:RSA、DH(Diffie-Hellman)、ECDH(Ellipticcurve Diffie–Hellman)。 這里看到使用的ECDH。
- ServerHello Done這個就是Server來表示自己說完了。類似電影里別人拿對講機說完話最后會有一個“完畢!”。

驗證證書有效性:
對端發來的證書簽名是 CA 私鑰加密的,接收到證書后,先讀取證書中的相關的明文信息,采用相同的散列函數計算得到信息摘要,然后利用對應 CA 的公鑰解密簽名數據,對比證書的信息摘要,如果一致,則可以確認證書的合法性;然后去查詢證書的吊銷情況等 (參考:https://www.codercto.com/a/24035.html)
第四步 Client => Server :Client Key Exchange、Change Cipher Spec、Encrypted Handshake Message
合法性驗證通過之后,客戶端計算產生隨機數字的預主密鑰(Pre-master),並用證書公鑰加密,發送給服務器並攜帶客戶端為密鑰交換提供的所有信息。這個消息受協商的密碼套件的影響,內容隨着不同的協商密碼套件而不同。
此時客戶端已經獲取全部的計算協商密鑰需要的信息: 兩個明文隨機數 random_C 和 random_S 與自己計算產生的 Pre-master,然后得到協商密鑰(用於之后的消息加密)
這次傳輸也包含三部分內容,也是做了一個優化
- Client Key Exchange 這個也是交換秘鑰參數。這里客戶端會再生成一個隨機數Random3。然后使用服務端傳來的公鑰進行加密得到密文PreMaster Key。服務端收到這個值后,使用私鑰進行解密,得到Random3。這樣客戶端和服務端就都擁有了Random1、Random2和Random3。這樣兩邊的秘鑰就協商好了。后面數據傳輸就可以用協商好的秘鑰進行加密和解密。
- Change Cipher Spec
編碼改變通知。這一步是客戶端通知服務端后面再發送的消息都會使用前面協商出來的秘鑰加密了,是一條事件消息。 - Encrypted Handshake Message
這一步對應的是 Client Finish 消息,客戶端將前面的握手消息生成摘要再用協商好的秘鑰加密,這是客戶端發出的第一條加密消息。服務端接收后會用秘鑰解密,能解出來說明前面協商出來的秘鑰是一致的。第五步 Server => Client:New Session Ticket、Change Cipher Spec、Encrypted Handshake Message
包括三部分
New Session Ticket
包含了一個加密通信所需要的信息,這些數據采用一個只有服務器知道的密鑰進行加密。目標是消除服務器需要維護每個客戶端的會話狀態緩存的要求。這部分內容在后面的擴展部分會講到
Change Cipher Spec
編碼改變通知。這一步是服務端通知客戶端后面再發送的消息都會使用加密,也是一條事件消息。
Encrypted Handshake Message
這一步對應的是 Server Finish 消息,服務端也會將握手過程的消息生成摘要再用秘鑰加密,這是服務端發出的第一條加密消息。客戶端接收后會用秘鑰解密,能解出來說明協商的秘鑰是一致的。
到這里雙方SSL/TLS握手完成。
摘要關鍵點:
握手的目標是安全地交換對稱密鑰,需要三個隨機數,第三個隨機數“Pre-Master”必須加密傳輸,絕對不能讓黑客破解;
“Hello”消息交換隨機數,“Key Exchange”消息交換“Pre-Master”;
“Change Cipher Spec”之前傳輸的都是明文,之后都是對稱密鑰加密的密文。
Https數據傳輸
接下來就真正的到了接口請求的階段。TLS的Content-Type為Application Data。 傳輸的內容也是加密的。
拓展內容=============================================
這部分對Https做一個深入的了解
TLS會話恢復
完整的TLS握手需要額外延遲和計算,為所有需要安全通信的應用帶來了嚴重的性能損耗。為了幫助減少一些性能損耗,TLS提供恢復機制,或多個連接之間共享相同的協商密鑰數據。
傳輸層安全(TLS)
會話標識
“會話標識符”(RFC 5246)恢復機制在SSL 2.0中首次被引入,它允許服務器在“ServerHello消息”中構建和發送一個32字節的會話標識符,作為“ServerHello”消息的一部分。
在服務器內部,服務器維護一個會話ID和其對應的協商參數的緩存。反過來,客戶端也同時存儲會話ID信息,在后續的會話中,可以在“ClientHello”消息中攜帶session ID信息,指示服務器它保存了session ID對應的密鑰和加密算法等信息,並且可以重用這些信息。假設在客戶端和服務器都能在它們各自的緩存中找到共享的會話ID參數,那么縮減的握手就可以進行了。否則,開始一個新的會話協商,這將產生一個新的會話ID。
我們演示一下,在前面抓包的的基礎上,我們再發一次請求。

最外面的紅框顯示了整個https訪問流程,內部的框是除去TCP握手和分手的的流程。我們將流程形象畫出來:

借助會話標識符,我們能夠減少一個完整的往返,以及用於協商的共享密鑰的公鑰加密算法開銷。這讓我們能快速的建立安全連接,而不損失安全性。我們看一下這個會話標識:

第二次的請求中的Client Hello的消息中Session Ticket有值了。
那這個Session Ticket是啥時候獲取的呢。我們繼續重溫下https握手流程,在最后一部。Server最后發給Client中,第一個消息就是New Session Ticket。我們看一下:

在實際應用中,大多數Web應用程序試圖通過建立到同一個主機的多個連接並行獲取資源,這使得會話恢復成為必不可少的一個優化項,其可以減少延遲,計算成本。
大多數現代瀏覽器都會有意的等待第一TLS連接完成后,再打開到同一台服務器的新連接:后續TLS連接,可以重復使用的SSL會話參數,以避免握手的延遲和損耗。
然而,“會話標識符”機制的一個限制就是要求服務器為每個客戶端創建和維護一個會話緩存。這會為服務器上帶來幾個問題,對於一些每天同時幾萬,甚至幾百萬的單獨連接的服務器來說:由於緩存session ID所需要的內存消耗將非常大,同時還有session ID清除策略的問題。這對一些流量大的網站來說不是一個簡單的任務,理想的情況下,使用一個共享的TLS會話緩存可以獲得最佳性能。
上述問題沒有是不可能解決的,許多高流量的網站成功的使用了會話標識符。但是,對任何多服務主機的部署,會話標識符方案需要一些認真的思考和好的系統架構,以確保良好的的會話緩存。
Session Tickets
為了解決上面的會話緩存帶來的服務器部署問題,“Sesion Ticket”(RFC 5077)取代機制被引入,目標是消除服務器需要維護每個客戶端的會話狀態緩存的要求。相反,如果客戶指示它支持Session Ticket,在TLS握手的最后一步中服務器將包含一個“New Session Ticket”信息,包含了一個加密通信所需要的信息,這些數據采用一個只有服務器知道的密鑰進行加密。
這個Session Ticket由客戶端進行存儲,並可以在隨后的一次會話中添加到 ClientHello消息的SessionTicket擴展中-因此,所有的會話信息只存儲在客戶端上,Session Ticket仍然是安全的,因為它是由只有服務器知道的密鑰加密的。
Session Identifiers和Session Ticket機制通常分別被稱為“會話緩存”和“無狀態恢復”機制。無狀態恢復的主要改進是消除服務器端的會話緩存,從而簡化了部署,它要求客戶在每一個新的會話開始時提供Session Ticket 直到Ticket過期。
在實際應用中,在一組負載平衡服務器中部署Session Ticket,也需要仔細考慮:所有的服務器都必須用相同的會話密鑰,或者可能需要額外的機制,定期輪流在所有服務器上的共享密鑰。
警告 會話票證破壞了 TLS 安全模型。它使票證密鑰加密的會話狀態並將其暴露在線路上。有些實現中的票證密鑰可能會比連接使用的密碼要弱。如果票證密鑰被暴露,就可以解密連接上的全部數據。因此,使用會話票證時,票證密鑰需要頻繁輪換。
SessionId和Session Ticket的區別
Session ID的思想就是服務器端為每一次的會話生成並記錄一個ID號並發送給客戶端,在重新連接的時候(多次短連接場景),客戶端向服務器發送該ID號,服務器查找自己的會話記錄,匹配之后,重用之前的加密參數信息。
而Sessionticket的思想類似於cookie,是由服務器將ticket數據結構發由客戶端管理,ticket中是包含了加密參數等連接信息。當需要重連的時候,客戶端將ticket發送給服務器。這樣雙方就得到了重用的加密參數。
Session ticket較之Session ID優勢在於服務器使用了負載均衡等技術的時候。Session ID往往是存儲在一台服務器上,當我向不同的服務器請求的時候,就無法復用之前的加密參數信息,而Session ticket可以較好的解決此類問題,因為相關的加密參數信息交由客戶端管理,服務器只要確認即可。
證書
證書種類
證書格式
一般來說,主流的 Web 服務軟件,通常都基於 OpenSSL 和 Java 兩種基礎密碼庫。
-
Tomcat、Weblogic、JBoss 等 Web 服務軟件,一般使用 Java 提供的密碼庫。通過 Java Development Kit (JDK)工具包中的 Keytool 工具,生成 Java Keystore(JKS)格式的證書文件。
-
Apache、Nginx 等 Web 服務軟件,一般使用 OpenSSL 工具提供的密碼庫,生成 PEM、KEY、CRT 等格式的證書文件。
-
IBM 的 Web 服務產品,如 Websphere、IBM Http Server(IHS)等,一般使用 IBM 產品自帶的 iKeyman 工具,生成 KDB 格式的證書文件。
-
微軟 Windows Server 中的 Internet Information Services(IIS)服務,使用 Windows 自帶的證書庫生成 PFX 格式的證書文件。
證書類型
您可以使用以下方法簡單區分帶有后綴擴展名的證書文件:
- *.DER 或 *.CER 文件: 這樣的證書文件是二進制格式,只含有證書信息,不包含私鑰。
- *.CRT 文件: 這樣的證書文件可以是二進制格式,也可以是文本格式,一般均為文本格式,功能與 *.DER 及 *.CER 證書文件相同。
- *.PEM 文件: 這樣的證書文件一般是文本格式,可以存放證書或私鑰,或者兩者都包含。 *.PEM 文件如果只包含私鑰,一般用 *.KEY 文件代替。
- *.PFX 或 *.P12 文件: 這樣的證書文件是二進制格式,同時包含證書和私鑰,且一般有密碼保護。
您也可以使用記事本直接打開證書文件。如果顯示的是規則的數字字母,例如:
—–BEGIN CERTIFICATE—– MIIE5zCCA8+gAwIBAgIQN+whYc2BgzAogau0dc3PtzANBgkqh...... —–END CERTIFICATE—–
那么,該證書文件是文本格式的。
如果存在——BEGIN CERTIFICATE——,則說明這是一個證書文件。
如果存在—–BEGIN RSA PRIVATE KEY—–,則說明這是一個私鑰文件。
更多內容參考主流數字證書都有哪些格式?
常見加密算法
- 非對稱加密算法:RSA,DSA/DSS
- 對稱加密算法:AES,RC4,3DES
- HASH算法:MD5,SHA1,SHA256
為啥數據傳輸時候用對稱加密?
RSA性能是非常低的,原因在於尋找大素數、大數計算、數據分割需要耗費很多的CPU周期,所以一般的HTTPS連接只在第一次握手時使用非對稱加密,通過握手交換對稱加密密鑰,在之后的通信走對稱加密。