https://xz.aliyun.com/t/1039html
握手消息 | 動做描述 | 消息內容 |
---|---|---|
1. Client —> ClientHello —> Server | 客戶端(瀏覽器)發送一個hello消息給服務端,發起創建SSL會話的請求。並告訴服務端,本身支持哪些加密算法(Cipher Suite List)。除此以外,還須要產生一個隨機數(第一個隨機數,用於之後生成對稱密鑰),發送給服務端。 | 1)支持的協議版本,如TLS 1.0版<br/>2)由客戶端生成的隨機數,用於生成後面的「對稱密鑰」<br/>3)支持的加密方法,好比RSA公鑰加密<br/>4)支持的壓縮方法<br/>5)請求的域名<br/> |
2. Server —> ServerHello —> Client | 服務端的首次響應,會肯定加密協議版本,以及加密的算法,也會生成一個隨機數(第二個隨機數)給客戶端。 | 1)協議的版本<br/>2)加密的算法<br/>3)服務端生成的隨機數<br/> |
3. Server —> Certificate —> Client | 還會把本身的證書發送給客戶端,讓客戶端進行校驗。服務端證書中的公鑰也可被用於加密後面握手過程當中生成的對稱密鑰。 | 1)服務端證書<br/>證書頒發機構的名稱<br/>證書自己的數字簽名<br/>證書持有者公鑰<br/>證書籤名用到的Hash算法<br/> |
4. Server --> ServerKeyExchange —> Client | 指定使用哪一種密鑰協商協議。服務端能夠在ServerKeyExchange以後當即發送CertificateRequest消息,要求校驗客戶端的證書。 | 1)使用哪一種密鑰協商方式<br/>2)密鑰協商時客戶端須要的信息 |
5. Server —> ServerHelloDone —> Client | 服務器發送ServerHelloDone消息,告知客戶端服務器這邊握手相關的消息發送完畢。 | |
6. Client —> ClientKeyExchange —> Server | 消息中包含客戶端這邊的EC Diffie-Hellman算法相關參數,而後服務器和客戶端均可根據接收到的對方參數和自身參數運算出對稱密鑰。 | 1)密鑰協商時服務端須要的信息 |
7. Client —> ChangeCipherSpec —> Server | ChangeCipherSpec消息,通知服務器此消息之後客戶端會以加密方式發送數據。 | 準備好了作加密傳輸的通知 |
8. Client —> Finished —> Server | 客戶端計算生成對稱密鑰,而後使用該對稱密鑰加密以前全部收發握手消息的Hash值,發送給服務器,服務器將相同的會話密鑰(使用相同方法生成)解密此消息,校驗其中的Hash值。 | |
9. Server —> ChangeCipherSpec —> Client | ChangeCipherSpec消息,通知客戶端此消息之後服務器會以加密方式發送數據。 | 準備好了作加密傳輸的通知 |
10. Server — > Finished —> Client | 服務器使用對稱密鑰加密(生成方式與客戶端相同)以前所發送的全部握手消息的hash值,發送給客戶端去校驗。 | |
11. Application Data | 真正的數據傳輸(使用對稱加密) |
struct { ProtocolVersion client_version; Random random; SessionID session_id; CipherSuite cipher_suites<2..2^16-2>; CompressionMethod compression_methods<1..2^8-1>; select (extensions_present) { case false: struct {}; case true: Extension extensions<0..2^16-1>; }; } ClientHello;
RSA
AEAD_AES_128_GCM
SHA256
ECDHE
struct { ProtocolVersion server_version; Random random; SessionID session_id; CipherSuite cipher_suite; CompressionMethod compression_method; select (extensions_present) { case false: struct {}; case true: Extension extensions<0..2^16-1>; }; } ServerHello;
公鑰
和私鑰
,公鑰會作到證書裏面,私鑰則會給到網站方。網站方的信息
和網站方的公鑰
、簽名算法
等信息(就是Wireshark Packet 20中的數據,除了「簽名值」),計算一個hash值(圖中hash算法是SHA256),而後CA再用本身私鑰作加密(圖中公開密鑰算法是RSA),最後的這個密文就是「數字簽名」(也就是咱們在圖中看到「encrypted」簽名值)。* 瀏覽器一般也會內置大多數主流權威CA的根證書。 * 若是查找不到對應的可信CA,則判斷這個證書是僞造的,不可信的。(瀏覽器則會提醒該證書不是可信任機構頒發的,並詢問是否要繼續訪問)
CA機構證書
裏面的公鑰
信息,將網站方證書
中的簽名值
(也就是數字簽名)作解密,獲得網站證書
信息的hash摘要A。網站證書
中的信息,作hash獲得摘要B,比對摘要A和摘要B是否一致。若是不一致,說明網站證書
中的信息被修改了。(瀏覽器則會提醒該證書不是可信任機構頒發的,並詢問是否要繼續訪問)公鑰
,用於後面的握手簽名。證書
公鑰對簽名值解密,得到摘要A。並將此次數據明文作SHA512的hash,得到摘要B,作比對。(這裏對協商算法作簽名校驗,目的多是防止中間人對協商算法方式作篡改,雖然DH算法不擔憂公鑰在不安全的網絡中傳輸,可是其餘算法可能須要考慮被篡改的狀況。因此猜想服務端密鑰協商時作簽名是這個目的,由於服務端這時已經肯定是DH算法了,因此客戶端協商時就不須要作簽名了,DH算法不須要考慮這個安全問題)服務端密鑰協商的公鑰以及本身的公鑰
EC Diffie-Hellman
密鑰協商協議爲例,來看看客戶端、服務端是怎麼協商出相同的密鑰的(這裏協商出來的是PreMasterSecret,不是最終的對稱加密用到的密鑰)。struct { opaque verify_data[verify_data_length]; } Finished; verify_data PRF(master_secret, finished_label,Hash(handshake_messages)) [0..verify_data_length-1];
struct { HandshakeType msg_type; /* handshake type */ uint24 length; /* bytes in message */ select (HandshakeType) { case hello_request: HelloRequest; //HelloRequest是服務端在任什麼時候候均可以發出的,告訴客戶端須要從新進行握手協議,客戶端隨即發送新的ClientHello case client_hello: ClientHello; case server_hello: ServerHello; case certificate: Certificate;//服務端或客戶端發送本身證書給客戶端。 case server_key_exchange: ServerKeyExchange; case certificate_request: CertificateRequest;//服務端請求,客戶端發送本身的客戶端證書,給服務端作校驗。這個步驟在博文中沒有提到,看之後有須要再瞭解。 case server_hello_done: ServerHelloDone; case certificate_verify: CertificateVerify;//客戶端發出,從client hello開始,一直到CertificateVerify以前的全部消息的hash加上客戶端證書對應私鑰的加密結果。 case client_key_exchange: ClientKeyExchange; case finished: Finished; } body; } Handshake;
struct { ProtocolVersion protocol_version; //協議版本 CipherSuite cipher_suite; //加密套件類型 CompressionMethod compression_method; //壓縮方法 opaque master_secret[48]; //對稱密鑰 ClientIdentity client_identity; //客戶端ID uint32 timestamp;//ticket有效期 } StatePlaintext;