Https之(一)TLS介紹及握手過程詳解

文章目錄

    • 簡介
    • TLS
      • TLS第一次握手
      • 1.Client Hello
      • TLS第二次握手
        • 2.Server Hello
        • 3.Certificate
        • 4.Server Hello Done
      • TLS第三次握手
        • 5.Client Key Exchange
        • 6.Change Cipher Spec
        • 7.Encrypted Handshake Message
      • TLS第四次握手
        • 8.New Session Ticket
        • 9.Change Cipher Spec
        • 10.Encrypted Handshake Message
    • 總結

簡介

我們知道http傳輸數據是明文傳輸,明文傳輸存在三個問題:

  1. 竊聽風險:由于是明文傳輸,到達目標之前的所有鏈路都可以看到傳輸的內容。
  2. 篡改風險:如果傳輸過程中間數據被修改,接收方也無法得知。
  3. 冒充風險:由于知道傳輸的內容,中間人可以冒充接收方。

在計算機發展的早期只是使用http傳輸簡單的數據,發展到現在絕大部分數據傳輸都是基于http協議,如果還使用明文傳輸顯然不太安全,特別是涉及賬號密碼相關的內容,https就是在http的基礎上添加了安全傳輸層,其中s代表SSL(Secure Sockets Layer)或者TLS(Transport Layer Security),SSL是早期的版本,由網景公司在1990年代早期開發。TLS是其后續版本,由互聯網工程任務組(IETF)開發,SSL有SSL1.0、SSL2.0和SSL3.0,TLS有TLS1.0、TLS1.1、TLS1.2和TLS1.3,目前主流的版本是TLS1.2和TLS1.3。下面我們來介紹TLS是怎么實現安全傳輸的。我們以目前主流的TLS1.2作為介紹對象。

TLS

我們先看下TLS的流程:

在這里插入圖片描述

根據上圖我們可以把TLS分為以下幾步:

1.服務端生成一對非對稱加密的密鑰對,把自己的公鑰交給CA機構生成一個證書,什么是CA呢?因為非對稱加密通過公鑰加密數據,通過私鑰解密數據,服務端擁有公鑰私鑰,但是客戶端什么都不知道,所以需要將公鑰傳給客戶端,但是直接發給客戶端可能會被中間人攔截替換,TLS通過引入一個雙方可以信任的第三方即CA來解決這個問題。

  • CA會將服務端的公鑰、頒發者、有效時間等信息打成一個包,然后對這些信息進行 Hash 計算,得到一個 Hash 值(也稱證書指紋)
  • 然后 CA 會使用自己的私鑰將該 Hash 值加密,生成 Certificate Signature(證書簽名)
  • 最后將 Certificate Signature 添加在文件證書上,形成數字證書。由于證書簽名使用CA的私鑰加密,解密自然只能用CA的公鑰。我們的客戶端(Android,Windows,iOS等)都會集成全球主流的CA的公鑰信息到操作系統中。

2.當客戶端向服務端請求數據的時候,服務端把這個證書發送給客戶端,客戶端拿到證書后可以得到服務端的公鑰、頒發者、有效時間、證書簽名和所屬的CA等信息。

  • 首先客戶端會使用同樣的 Hash 算法獲取該證書的 Hash 值 H1
  • 再從操作系統中尋找這個CA的公鑰,通過公鑰解密證書里的簽名數據得到Hash值H2
  • 最后比較 H1 和 H2,如果值相同,則為可信賴的證書。

通過CA客戶端可以驗證服務端的身份,防止有人冒充。

3.客戶端已經拿到了可以用來加密的公鑰,正常來說現在已經可以進行加密通訊了,但是由于非對稱加密較復雜,加密耗時較久,而且加密后內容明顯變大,所以在頻繁的通訊中使用是非常不劃算的,所以這里并沒有直接用公鑰加密傳輸數據,而是引入了對稱加密,在客戶端隨機生成一個對稱加密密鑰,并使用公鑰加密后傳給服務器,由于只有服務器有私鑰,所以中間攔截也沒用,服務器接收到數據后解密拿到對稱加密密鑰,后續的通訊就使用對稱加密進行加密。(雖然對稱加密的安全性不如非對稱加密,但是由于每次連接都會生成一個隨機的密鑰,所以安全性上也是可以接受的。)

上面只是大致的流程,實際實現和上面說的還是有很大區別的,下面我們分析一次實際中TLS握手的完整過程,什么是TLS的握手呢?其實就是通訊雙方通過上面的方法協商一個共同的密鑰的過程,他的完整流程是這樣的:

請添加圖片描述

上圖有多次通信過程,可以分成4次握手,下面我們通過抓包看一下實際的TLS的握手過程,首先看一下wireshark中完整的TLS握手記錄:

請添加圖片描述

上圖中有多個握手過程,我把其中一個握手的完整過程標記出來了,下面我們來詳細介紹每一步的作用。

TLS第一次握手

1.Client Hello

請添加圖片描述

上圖是client hello的所有內容,我們重點關注紅框中的內容:

1.Version是客戶端的TLS版本,我們看到是1.2

2.Random是客戶端生成的一個隨機數,用于生成加密密鑰,前面我們說過客戶端拿到服務端公鑰后會生成一個隨機數當作后續通訊加密的密鑰,并把這個密鑰用公鑰加密后發送給服務端,其實這個密鑰不止一個隨機數,而是三個隨機數拼成的,其一就是這里的隨機數,其二是服務端server hello時也會傳過來的一個服務端生成的隨機數,最后才是之前說的隨機數,通過三個隨機數生成最終的密鑰是為了保證隨機性和安全性。

3.Cipher Suites是客戶端支持的加密套件,我們上面說的對稱加密和非對稱加密并沒有固定的加密算法,這個有很多選擇,我們看下客戶端支持的加密套件有哪些:
請添加圖片描述

這個密碼套件看起來真讓人頭暈,好一大串,但是其實它是有固定格式和規范的。基本的形式是「密鑰交換算法 + 簽名算法 + 對稱加密算法 + 摘要算法」, 一般 WITH 單詞前面有兩個單詞,第一個單詞是約定密鑰交換的算法,第二個單詞是約定證書的驗證算法。比如我們目前分析的這個TLS_RSA_WITH_AES_128_GCM_SHA256密碼套件的意思就是:

  • 由于 WITH 單詞只有一個 RSA,則說明握手時密鑰交換算法和簽名算法都是使用 RSA;
  • 握手后的通信使用 AES 對稱算法,密鑰長度 128 位,分組模式是 GCM;
  • 摘要算法 SHA256 用于消息認證和產生隨機數;

4.support_versions是客戶端支持的所有TLS版本,前面的version是客戶端想要使用的版本,但是服務端不一定支持,所以需要把支持所有版本給到服務端,如果服務端不支持version的版本,就在support_versions選一個。

5.session_ticket是用于復用之前的TLS連接用的,這個后面會介紹。

TLS第二次握手

2.Server Hello

請添加圖片描述

1.Version是服務端選擇的TLS版本

2.Random是服務端生成的一個隨機數,用于生成加密密鑰

3.Cipher Suites是服務端選擇的加密套件

3.Certificate

請添加圖片描述

這一步是將服務器的證書發送給客戶端,客戶端拿到證書后會去進行驗證,并拿到公鑰。

上圖中服務器給了兩個證書,這是為什么呢?這就要說到CA的證書鏈機制了,服務端的證書并不一定是CA根證書簽發的,而可能是CA的二級證書簽發的,CA下面會有二級三級乃至多級代理,如果是二級代理簽發的證書,就要先用根證書驗證二級代理的證書,二級代理的證書沒問題,再用二級代理的證書驗證服務器的證書。

所以上圖的第一個證書是服務器證書,第二個證書是二級代理的證書,先找到二級代理所屬的CA,去驗證二級證書,驗證無誤后再用二級證書去驗證服務器證書。

請添加圖片描述

4.Server Hello Done

請添加圖片描述

服務端已經完成hello,為什么需要這一步呢?

Server Hello之后,服務器通常會發送一系列消息,包括:

  • Certificate (包含服務器的證書鏈)
  • Server Key Exchange (如果證書不包含足夠的信息進行密鑰交換,例如使用DHE/ECDHE算法時)
  • Certificate Request (可選,如果服務器要求客戶端認證)
  • ... (其他可能的擴展消息)

這些消息的數量和類型是可變的,取決于協商的加密套件、服務器配置和是否要求客戶端認證。

Server Hello Done 的唯一作用就是清晰、明確地告訴客戶端:“我已經發送完所有我這邊在握手這一階段需要發送的信息了,沒有更多這類消息了。”

TLS第三次握手

5.Client Key Exchange

請添加圖片描述

將用公鑰加密的pre-master傳遞給服務端,服務端拿到直接用私鑰解密就可以拿到pre-master,加上client的random和server的radom就可以得到回話密鑰。

客戶端隨機數 + 服務端隨機數 + 預主密鑰 = 主密鑰 ==> 會話密鑰

6.Change Cipher Spec

請添加圖片描述

告訴服務端開始用會話密鑰進行加密通訊了

7.Encrypted Handshake Message

請添加圖片描述
把客戶端之前所有發送的數據做個摘要,再用會話密鑰(master secret)加密一下,讓服務器做個驗證,驗證加密通信是否可用和之前握手信息是否有被中途篡改過。

TLS第四次握手

8.New Session Ticket

請添加圖片描述
將session_ticket發送給客戶端保存,session_ticket是用于復用之前的TLS連接用的,由于TLS的握手比較繁瑣,自然就比較耗時,所以當握手完成后服務器端將本次的會話數據進行加密(會話標識符、證書、密碼套件和主密鑰等),加密后生成一個ticket票據(只有服務器可以解密),并將票據通過NewSessionTicket子消息發送給客戶端,客戶端保存這個ticket。當連接斷開后重新連接的時候就可以在client hello中將這個ticket發送給服務端,服務器端解密校驗無誤后拿到主密鑰,將主密鑰和client hello中的random以及服務端生成的即將在server hello中傳輸的random三個數據生成一個新的密鑰,然后server hello的時候客戶端也用同樣的三個數據生成這個密鑰,這樣就協商了一個相同的密鑰,后續就用這個密鑰進行加密通訊,如此恢復上一次會話就可以省掉之后的很多步驟。

9.Change Cipher Spec

和客戶端發送的Change Cipher Spec操作相同,告訴客戶端我準備好使用會話密鑰了

10.Encrypted Handshake Message

把服務端之前所有發送的數據做個摘要,再用會話密鑰(master secret)加密一下,讓客戶端做個驗證,驗證加密通信是否可用和之前握手信息是否有被中途篡改過。

總結

到這里TLS的流程就介紹完了,我們再看看開頭說的http的三個問題是怎么解決的:

  1. 竊聽風險:通過會話密鑰加密數據。
  2. 篡改風險:通過CA對證書進行簽名,對TLS握手過程進行摘要計算。
  3. 冒充風險:向CA驗證證書。

雖然解決了這三個問題,但是現在的TLS還是有缺陷的,那就是不支持前向保密,因為客戶端傳遞pre-master(用于生成對稱加密密鑰的條件之一)給服務端時使用的是公鑰加密的,服務端收到后,會用私鑰解密得到隨機數。所以一旦服務端的私鑰泄漏了,過去被第三方截獲的所有 TLS 通訊密文都會被破解。

為了解決這一問題,于是就有了 DH 密鑰協商算法TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,和我們上面介紹的TLS_RSA_WITH_AES_128_GCM_SHA256區別就是使用了ECDHE的密鑰協商算法,后面我們介紹一下這個算法。

下一篇:Https之(二)TLS的DH密鑰協商算法

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/94047.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/94047.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/94047.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【WEB 】從零實現一個交互輪播圖(附源碼)

文章目錄 一、輪播圖整體功能規劃二、HTML結構深度解析三、CSS樣式實現細節1. 定位系統詳解2. 顯示/隱藏機制3. 按鈕交互效果實現4. 純CSS箭頭實現5. 指示器:當前位置可視化 四、JavaScript邏輯深入解析1. 核心變量與DOM獲取2. 圖片切換函數(核心邏輯&am…

機器學習--PCA降維

一核心部分 1解決的問題:應對高維數據帶來的計算量大、冗余信息多、易出現過擬合等問題,在減少數據維度的同時盡可能保留原始數據的關鍵信息。2核心思想&#xff1a…

leetcode 1277. 統計全為 1 的正方形子矩陣 中等

給你一個 m * n 的矩陣,矩陣中的元素不是 0 就是 1,請你統計并返回其中完全由 1 組成的 正方形 子矩陣的個數。示例 1:輸入:matrix [[0,1,1,1],[1,1,1,1],[0,1,1,1] ] 輸出:15 解釋: 邊長為 1 的正方形有…

知識蒸餾 - 各類概率分布

知識蒸餾 - 各類概率分布 flyfish一、離散概率分布 離散分布描述的是取值為離散值(如0,1,2,…)的隨機變量的概率規律,通常用概率質量函數(PMF) 表示某一取值的概率。 1. 伯努利分布(Bernoulli Distribution…

軟件測試-Selenium學習筆記

""" 目標: driver.find_element() 需求: 1. 使用driver.find_element()方法 2. 輸入用戶名:admin 3. 輸入密碼:123456 """ # 導包 from selenium import webdriver from time import …

知微傳感3D相機上位機DkamViewer使用:給相機升級固件

寫在前面 本人從事機器視覺細分的3D相機行業。編寫此系列文章主要目的有: 1、便利他人應用相機,本系列文章包含公司所出售相機的SDK的使用例程及詳細注釋;2、促進行業發展及交流。 知微傳感Dkam系列3D相機可以應用于定位分揀、焊接焊縫提取、…

CMake進階: CMake Modules---簡化CMake配置的利器

目錄 1.簡介 2.為什么需要 CMake Modules? 3.內置模塊:開箱即用的工具 3.1.依賴查找模塊(FindXXX.cmake) 3.2.功能檢測模塊(CheckXXX.cmake) 3.3.通用工具模塊(如 FetchContent.cmake、CT…

【Docker】Ubuntu上安裝Docker(網絡版)

【Docker】Ubuntu上安裝Docker注意:一、環境準備1. 系統要求2. 卸載舊版本二、安裝步驟1.配置倉庫源2.安裝 Docker引擎3.驗證安裝情況三、解決報錯1、檢查網絡連接2、檢查Docker服務狀態3、換源4.重載生效、重啟服務、查看是否配置成功5.驗證解決情況四、權限與配置…

Socket 編程 TCP

TCP 網絡程序 和剛才 UDP 類似. 實現一個簡單的英譯漢的功能。TCP是面向字節流的可靠傳輸,如同前文的管道流,只要是流,它的操作就是文件的寫出與讀入。TCP socket API 詳解下面介紹程序中用到的 socket API,這些函數都在 sys/socket.h 中。so…

使用AWS S3 + Lambda + MediaConvert 實現上傳視頻文件并自動轉碼

前言 最近團隊在做短視頻平臺的技術調研,其中有一個環節便是音視頻開發,即對用戶上傳的視頻進行自適應轉碼。自適應的原理其實就是預先將視頻轉換為幾個常用的分辨率,app端根據用戶手機分辨率拉取相應分辨率的視頻。 目前嘗試了兩種方案&…

QT之QWaitCondition降低cpu占用率,從忙等待到高效同步

在多線程編程中,線程間的同步是一個核心問題。在處理線程等待時,經常會寫出高CPU占用率的代碼,其中最典型的就是使用忙等待(busy waiting)。本文將詳細介紹如何使用Qt框架中的QWaitCondition類來優雅地解決這一問題&am…

pcl求平面點云的邊界凸包點

基本流程1,讀入點云,并去除無效點2,擬合平面3,去除離平面距離較遠的點4,對點云進行平面投影5,進行convex_hull運算初學者,暫時不知道能用來干嘛。練手還是非常不錯的!#define _CRT_S…

Windows系統上使用GIT

首先破除一下畏懼心理:在Windows上使用git和在linux系統中的使用方法是一樣的,只是安裝方式沒那么便捷,畢竟linux中安裝git只需要一行命令 GIT下載地址 如果你的電腦的CPU是64位的,就點擊: Git-2.50.1-64-bit.exe 如果…

《設計模式之禪》筆記摘錄 - 17.模板方法模式

模板方法模式的定義模板方法模式(Template Method Pattern)是如此簡單,以致讓你感覺你已經能夠掌握其精髓了。其定義如下:Define the skeleton of an algorithm in an operation, deferring some steps to subclasses.Template Method lets subclasses r…

SpreadJS 協同服務器 MongoDB 數據庫適配支持

為了支持 SpreadJS 協同編輯場景,協同服務器需要持久化存儲文檔、操作、快照及里程碑數據。本文介紹了 MongoDB 數據庫適配器的實現方法,包括集合初始化、適配器接口實現以及里程碑存儲支持。 一、MongoDB 集合初始化 協同編輯服務需要以下集合&#x…

Ubuntu 主機名:精通配置與管理

主機名(hostname)是Linux系統中用于標識網絡上特定設備的名稱,它在網絡通信、服務配置(如 Kubernetes 集群、數據庫)以及日志記錄中扮演著至關重要的角色。對于初學者來說,配置主機名似乎很簡單&#xff0c…

C/C++ 協程:Stackful 手動控制的工程必然性

🚀 C/C 協程:Stackful 手動控制的工程必然性 引用: C/C 如何正確的切換協同程序?(基于協程的并行架構) #mermaid-svg-SXgplRf3WRYc8A7l {font-family:"trebuchet ms",verdana,arial,sans-serif;…

新手向:使用STM32通過RS485通信接口控制步進電機

新手向:使用STM32通過RS485通信接口控制步進電機 準備工作 本文使用的STM32芯片是STM32F407ZGTx,使用的電機是57步進電機,驅動器是用的是時代超群的RS485總線一體化步進電機驅動器(42 型:ZD-M42P-485)。使…

設計模式筆記_行為型_命令模式

1.命令模式介紹命令模式(Command Pattern)是一種行為設計模式,它將請求或操作封裝為對象,使得可以用不同的請求對客戶端進行參數化。命令模式的核心思想是將方法調用、請求或操作封裝到一個獨立的命令對象中,從而使得客…

詳解MySQL中的多表查詢:多表查詢分類講解、七種JOIN操作的實現

精選專欄鏈接 🔗 MySQL技術筆記專欄Redis技術筆記專欄大模型搭建專欄Python學習筆記專欄深度學習算法專欄 歡迎訂閱,點贊+關注,每日精進1%,與百萬開發者共攀技術珠峰 更多內容持續更新中!希望能給大家帶來…