%% # 纲要 > 主干纲要、Hint/线索/路标 # Q&A #### 已明确 #### 待明确 > 当下仍存有的疑惑 **❓<font color="#c0504d"> 有什么问题?</font>** # Buffer ## 闪念 > sudden idea ## 候选资料 > Read it later %% # SSL 协议 > **SSL(Secure Socketes Layer)安全套接层** 是一种网络安全协议,旨在为互联网通信提供安全和数据加密。 SSL 最初由 Netscape 于 1990 年代中期开发,是早期用于保护网络通信的加密协议。 后来随着 SSL 被广泛应用,成为互联网上的**事实标准**,故互联网工程任务组(IETF)**在 1999 年将其改进和标准化**,重新命名为 **TLS(传输层安全协议)**。 因此,"**SSL**" 术语实际**泛指 SSL/TLS 协议**,二者可视为同一协议的不同阶段。 # TLS 协议 > TLS(Transport Layer Security),**传输层安全协议**。 TLS 由 IETF 组织 **对 SSL 进行标准化** 所得,有 TLS 1.0、1.1、1.2 和 1.3 多个版本,每个新版本都增强了安全性和性能: | 版本 | 发布年份 | 主要改进 | | ----------- | ---- | ----------------------------- | | SSL 3.0 | 1996 | 已废弃,不安全 | | TLS 1.0 | 1999 | 取代 SSL 3.0,改进安全性(已废弃) | | TLS 1.1 | 2006 | 改进 CBC 加密模式(已废弃) | | **TLS 1.2** | 2008 | 支持 SHA-256,改进加密(仍在使用) | | **TLS 1.3** | 2018 | 简化握手过程,移除不安全的加密算法(如 RSA 密钥交换) | <br><br> # TLS 提供的功能 TLS 协议位于**应用层**与**传输层**之间,旨在为网络通信提供**加密、安全性和数据完整性**保障, 被广泛应用于 **HTTPS、FTPS、SMTP、IMAP、VoIP** 等需要安全通信的场景。 TLS 协议提供的功能: - **==加密通信==** => 传输数据加密,**防窃取** - TLS 在握手过程中使用 **==非对称加密==** (RSA 或 ECDHE 密钥交换)来安全地 **==交换对称加密密钥==**。 - TLS 在建立连接后使用 **==对称加密==** 进行数据传输,同时提供完整性检查机制,确保数据在传输过程中未被篡改。 - **基于==数字证书==的身份认证** => 验证网站身份,**防止客户端访问伪造网站**,**防止中间人攻击**。 - 服务器提供 **X.509 数字证书** 供客户端进行身份验证(如 HTTPS 网站使用 **CA 颁发的 SSL/TLS 数字证书**) - **数据==完整性校验==** => 确保传输的数据未被篡改。 - 采用**消息认证码**(MAC,如 HMAC)校验数据完整性。 - **会话恢复** - TLS 支持会话恢复功能,可以**在连接中断后快速恢复加密通信**,而**无需重新进行完整的握手**。 TLS 在实现上分为两层:「**握手协议**」与 「**==记录协议==**」 - 握手协议:即 TLS 握手过程,负责 **协商加密算法、验证身份和生成对称密钥** - **记录协议**:负责 **==数据加密== & ==完整性校验==** => 例如,对 HTTP 数据加密是由该层负责 > [!NOTE] TLS 协议的两层 > > 其中,握手协议这一层,又细分为具体的 4 个子协议。 > > - **握手协议**(Handshake Protocol):负责 TLS 连接建立; > - **警报协议**(Alert Protocol):负责发送 **TLS 连接异常的情况,如证书无效、连接关闭**。 > - **密码变更协议**(ChangeCipherSpec Protocol):负责通知对端,后续数据将使用新的加密算法(仅 TLS1.2,在 TLS1.3 中已移除) > - **应用数据协议**(Application Data Protocol):负责 "**传输**" 加密后的应用层数据。 > > ![[_attachment/02-开发笔记/07-计算机网络/传输层/SSL & TLS 协议.assets/IMG-SSL & TLS 协议-3290233AD328571DBF49F0CC6DA6085A.png|612]] > <br><br><br> # TLS 握手过程 客户端与服务器通过 "**握手过程**" 实现下列目的: - (1)**==协商加密算法==** - 确定 TLS 版本; - 确定将采用的**加密算法**(如 AES、ChaCha20) - 确定**密钥交换方式**(如 RSA、ECDHE) - (2)**==验证身份==**: - 服务器端提供其**数字证书**(包含公钥),**供客户端认证**; - 需 **双向验证** 时,客户端也提供其数字证书。 - (3)**==完成密钥交换==** - 交换 "**密钥交换算法**" 所需的信息,用于最后计算**生成**相同的 "**==共享对称密钥==**",以供对后续通信数据进行加密。 - 例如 RSA 所需的服务器公钥加密后的 **Pre-Master Secret**,**ECDHE 所需的公钥参数**; <br> ## TLS 1.2、TLS 1.3 握手过程总结 ![[_attachment/02-开发笔记/07-计算机网络/传输层/SSL & TLS 协议.assets/IMG-SSL & TLS 协议-5E5727C656F97036356592178D0270F1.png|659]] - TLS 1.2:**四次握手**,**2-RTT**; - TLS 1.3:**三次握手**,**1-RTT**(会话恢复时可实现 0-RTT) <br><br> ## TLS 1.2 握手过程 共 **四次握手**,需要 **==2-RTT==** 时延才能完成**密钥交换**(对于**单端**而言) - **第一次握手**:由客户端发送: - `ClientHello` : - TLS 版本、**支持的加密算法**、**随机数**(客户端生成)、**扩展字段**(例如 Session ID,用于会话恢复) - **第二次握手**:由服务器发送: - `ServerHello`: - TLS 版本、**==选定==的加密算法** 、**随机数**(服务器生成)、**扩展字段**(例如 Session ID,用于会话恢复) - `Certificate`: - 即 **==服务器证书==**(包含有**服务器公钥**、域名) - `ServerKeyExchange`(可选,**仅当使用 DH/ECDHE 密钥交换时**): - 发送服务器的 ECDHE 公钥,用于后续密钥协商,同时服务器使用**其私钥**对参数进行**签名** - `ServerHelloDone`: - 结束标志,标识**服务器端握手部分结束**。 - **第三次握手**:由客户端发送: - `Certificate`(可选,仅当需双**向身份验证**时) - 即 **==客户端证书==**; - `ClientKeyExchange`: - 若使用 RSA 密钥交换:生成 **Pre-Master Secret**(48 字节随机数),使用 **"服务器的公钥"** 加密后发送; - 若使用 DH/ECDHE 密钥交换:发送客户端的 ECDHE 公钥; - `Certificate Verify`(仅当发送了客户端证书时) - 使用 **客户端的私钥** 对握手信息签名 - `ChangeCpipherSpec`: - 标识**此后的通信将进行==加密==** - `Finished`: - 标志**客户端完成握手**;使用密钥计算握手摘要(HMAC 校验),服务器据此验证握手数据完整性 - **第四次握手**:由服务器发送: - `ChangeCpipherSpec`: - 标识**此后的通信将进行==加密==** - `Finished`: - 标志**服务器确认握手完成**,进入加密 > [!info] Finished 报文会通过 HMAC 校验握手数据完整性,确认未被篡改。 > [!info] TSL 1.2 ——四次握手 > ![[_attachment/02-开发笔记/07-计算机网络/传输层/SSL & TLS 协议.assets/IMG-SSL & TLS 协议-4C121859F21A0883250283E24ED61F39.png]] <br><br> ## TLS 1.3 握手过程 共**三次握手**,只需要 **==1-RTT==**(对于**单端**而言)。 - **第一次握手**:由客户端发送: - `ClientHello` : - TLS 版本、**支持的加密算法**、**随机数**(客户端生成)、**==预共享密钥==** - **第二次握手**:由服务器发送: - `ServerHello`: - TLS 版本、**==选定==的加密算法** 、**随机数**(服务器生成) - `Certificate`: - 即 **==服务器证书==**(包含有**服务器公钥**、域名) - `Finished`: - 标志**服务器确认握手完成**,进入加密 - **第三次握手**:由客户端发送: - `Finished`: - 标志**客户端完成握手** > [!info] TLS 1.3 的第三次握手可携带 "==应用层数据==" > [!info] TLS 1.3 ——三次握手 > ![[_attachment/02-开发笔记/07-计算机网络/传输层/SSL & TLS 协议.assets/IMG-SSL & TLS 协议-99F70B3C1719705966910D61F60D4730.png|525]] > [!summary] 相较于 TLS 1.2 中四次握手的优化: > > - **密钥协商提前进行**(只支持 DH/ECDHE),客户端首次握手时就提供其 **ECDHE 公钥**,相当于**合并了原客户端的第 1、3 次握手**。 <br><br> ### 0-RTT 握手(会话恢复) 在 TLS 1.3 中,如果客户端 **之前已经和服务器通信过**,且 **==缓存==了服务器的密钥信息**(Session Ticket), 则可以在**第一次消息(ClientHello)** 中就**直接发送加密的应用数据**,从而实现 **==0-RTT==**(即 **不需要等待服务器回应**),如下图所示: > [!info] 适用于**快速恢复 HTTPS 连接**,如浏览器短时间内重新访问同一网站 ![[_attachment/02-开发笔记/07-计算机网络/传输层/SSL & TLS 协议.assets/IMG-SSL & TLS 协议-4AF846D0A7788B80B793D575FE5DDECA.png|719]] --- <br><br><br> # 密钥交换/协商 "**密钥交换**" 是指**客户端与服务器** 通过协商生成得到一个"**共享的==对称密钥==**",该密钥用于 TLS 握手完成后**对后续传输数据进行加密**。 TLS 在建立连接后使用 **==对称加密==** 进行数据传输,因此客户端与服务器需要**共享密钥**。 由于 **不能在握手过程直接明文传输**,故采用 "**==密钥交换算法==**" 来安全地生成 **共享密钥**。 TLS 1.2 与 TLS 1.3 中,主要有两种密钥交换方式: - **RSA 密钥交换** - **DH/ECDHE 密钥交换** > [!caution] TLS 1.3 中已移除 RSA 方式,仅支持 DH/ECDHE 密钥交换 > > 原因在于 RSA 方式不够安全: > > - RSA 不支持 "**前向安全性**"(PFS):若**服务器的私钥**泄露,所有历史通信都可以被解密。 > - ECDHE 支持 "**前向安全性**"(PFS):即使服务器私钥泄露,**历史数据也无法解密**。 > [!faq] ❓ 为什么密钥协商过程需要 **"==双端的随机数=="**? > > **防止密钥重用**。 > > 最终 "共享对称密钥" 的计算中,包含 "双端随机数" 作为参数。 > 由此保证即使 **RSA 中的 Pre-Master Secret 或者 ECDHE 计算出的共享密钥 $Z$ 偶然相同**, > 但由于**每次握手时生成的随机数不同**,因此最终生成的 "**共享对称密钥**" 也不同。 > <br> ## RSA 密钥交换 交换/协商过程: 1. 服务器通过**握手报文 `Certificate`** 发送的**数字证书**中提供其 **RSA 公钥**; 2. 客户端生成 **Pre-Master Secret**(48 字节随机数),并使用 **服务器的 RSA 公钥** 加密后,通过握手报文 `ClientKeyExchange` 发送给服务器; 3. 服务器使用其 **私钥** 进行解密,获取 **Pre-Master Secret**; 4. 客户端 & 服务器用 **Pre-Master Secret** + **客户端随机数** + **服务器随机数** 计算处最终的 **共享对称密钥**; **共享对称密钥的计算**: 公式:`Master_Secret = PRF(Pre-Master_Secret, "master secret", Client_Random + Server_Random)` - `PRF` 是伪随机函数(通常是 HMAC-SHA256) - `"master secret"` 是某个固定字符串(由 TLS 规范中定义) <br> ## ECDHE 密钥交换 > ECDHE(椭圆曲线 Diffie-Hellman Ephemeral) 交换/协商过程: 1. 服务器生成自己的 **ECDHE 密钥对**,保留私钥,并将 **==公钥==** 通过握手报文 ServerKeyExchange 发送给客户端。 2. 客户端生成自己的 **ECDHE 密钥对**,保留私钥,并将 **==公钥==** 通过握手报文 ClientKeyExchange 发送给服务器。 3. 客户端、服务器计算得到 **==相同的 ECDHE 共享密钥==** $Z$; 4. 客户端 & 服务器使用 **Diffie-Hellman 算法** 计算出最终的 **共享对称密钥**。 > [!noe] 通过 "**DH/ECDHE 密钥对**" 计算得到 **"相同的 ECDHE 共享密钥**" 的说明 > > 例如: > > - 服务器:私钥 $d_s$,公钥 $Q_s = d_s * G$; > - 客户端:私钥 $d_c$,公钥 $Q_c = d_c * G$; > > 双方**交换 ECDHE 公钥**后,计算得到相同的**ECDHE 共享密钥**: $Z = d_c * Q_s = d_s * Q_c = d_c * d_s * G$ **共享对称密钥的计算**: 公式:`Master_Secret = PRF(Z, "master secret", Client_Random + Server_Random)` - `PRF` 是伪随机函数(通常是 HMAC-SHA256) - `Z` 是 ECDHE 计算出的共享密钥 - `"master secret"` 是固定字符串(由 TLS 规范中定义) <br><br> # 完整性校验 TLS 的完整性校验方式: 采用 **MAC** 或 **AEAD** 来实现完整性校验: - TLS 1.2:使用 **==HMAC==** 进行**完整性校验**(**基于哈希的消息认证码**,Message Authentication Code,MAC) - 需要**先根据原始数据计算 HMAC**,再加密数据,效率较低; - TLS 1.3:使用 **==AEAD==** 同时进行 **==加密== & 完整性校验**(**认证加密**,Authenticated Encryption with Associated Data,AEAD) - AEAD 直接**集成加密和完整性校验**,更高效; <br> ## HMAC 完整性校验 服务器和客户端使用 **==共享对称密钥==** 对传输的原始数据**计算 HMAC 值**,并将 **HMAC 值附加到数据包中**,一同加密传输。 接收方对收到的数据包**解密**后,**再次对原始数据计算 HMAC 值**,若与携带的 HMAC 值不匹配,说明数据不完整,可能已被**篡改**。 > [!info] 通常可使用 `SHA-256` 或 `SHA1`作为哈希函数 > [!NOTE] HMAC 校验过程说明 > > **HMAC 值附加到数据包尾**,再一同进行加密: > > ![[_attachment/02-开发笔记/07-计算机网络/传输层/SSL & TLS 协议.assets/IMG-SSL & TLS 协议-54436673D79F7C93ABFF24A5BBF258DC.png|542]] > 解密后对原内容**再次计算 HMAC 值**,比对是否与数据包携带的 HMAC 值相同: > > ![[_attachment/02-开发笔记/07-计算机网络/传输层/SSL & TLS 协议.assets/IMG-SSL & TLS 协议-3F610CCC470E35D24A3D18598A8ABAC3.png|504]] > <br> ## AEAD 认证加密 AEAD 算法提供 "**一体化加密认证**",即同时提供 "**==数据加密==**" & "**==完整性校验==**" 两项功能,**防止数据被窃取 or 篡改**。 常见的 AEAD 算法: - **AES-GCM(Galois/Counter Mode)** - **ChaCha20-Poly1305** #### AEAD 校验步骤 - **发送方使用 AEAD 加密数据**: - AEAD 加密接口直接返回 **==加密后数据==**(其中**已包含用于完整性校验的 Tag**) - `Ciphertext = AEAD_Encrypt(Key, Nonce, Plaintext, AdditionalData)` - `Nonce` 为随机数,确保唯一性; - **接收方使用 AEAD 解密数据**: - AEAD 解密接口直接接收 **==加密数据==**,解密时**自动提取 `Tag` 并验证完整性**。 - `Plaintext = AEAD_Decrypt(Key, Nonce, Ciphertext, AdditionalData)` - 若 `tag` 验证不通过,将返回错误或 `null`,表示**解密失败 <br><br><br> # 数字证书 数字证书(**==X.509 证书==**)由 **可信的第三方==证书颁发机构==(CA)** 签发。 企业实体可向 CA 申请证书,由 **CA 验证其身份(检查组织法律文件、域名所有权等)** 后颁发。 **数字证书**上包含以下内容: - **服务器公钥** - **服务器域名** - **证书颁发机构(CA)的签名**——由 **==CA 用其私钥==** 对 **申请者的公钥** 及其身份信息进行**数字签名**; - **有效期** - ......等等 ## 数字证书的使用 - (1)**服务器端使用证书**: - 实体将其**数字证书部署在服务器上**(如在 Web 服务器上用于 HTTPS), 当客户端通过 SSL/TLS 连接到服务器时,**服务器会在==SSL/TLS 握手过程==提供其数字证书**。 - (2)**客户端验证==证书==的有效性**,包括: - 证书**是否由可信的 CA 签发**; - 证书**是否在有效期内**; - 证书**域名是否与服务器域名匹配**; - 证书的**签名是否有效**——**==使用 CA 的公钥验证数字签名==**,**CA 的公钥内置于浏览器中** > [!NOTE] 数字证书 "签发" & "验证" 的流程 > ![[_attachment/02-开发笔记/07-计算机网络/传输层/SSL & TLS 协议.assets/IMG-SSL & TLS 协议-7FFC23F9DC002A775E3903EBB52B3CAC.png|524]] > > > [!NOTE] 数字证书 "签名" & "验证" 的具体操作 > > - 私钥签名:CA 用其**私钥**对 "**数字证书内容的==哈希值==**" 进行加密; > - 公钥验证:客户端用 **CA 的公钥** 进行验证: > 1. 客户端对 "**数字证书内容**" 再次计算**哈希值** H1; > 2. 客户端用 "**CA 的公钥**" 对数字签名进行**解密**,得到**哈希值 H2**; > 3. **比对两哈希值**,若相同则认证成功,否则认证失败。 > > ![[_attachment/02-开发笔记/07-计算机网络/网络安全相关.assets/IMG-网络安全相关-6BB7C408182E06E4798B063A63BAD849.png|660]] > <br> ## 证书信任链 TLS 协议中,数字证书实际上是通过 "**认证链**"(Certificate Chain)完成身份验证的,包含 **==三个层级==的认证过程**,最终**追溯到一个可信的==根证书== (Root CA)**。 **三层认证链**: 1. **服务器证书** - 由 **==中间 CA== 的私钥** 签发,由服务器在 TLS 握手过程中传递给客户端,交由客户端验证; 2. **中间 CA 证书**(一个或多个?) - 由 ==**根 CA== 的私钥** 签发,由服务器在 TLS 握手过程中**一并传递**给客户端,交由客户端验证; 3. **根 CA 证书** - 由 ==**根 CA== 的私钥**进行**自签名**; - 操作系统、浏览器等客户端内置有 "**==根 CA 证书==**" (证书上包含**根 CA 的公钥**) > [!note] TLS 握手过程中,服务器传输的证书包括 "**==服务器证书==**" 以及 "**==中间 CA 证书==**"(不含根 CA 证书) > > 认证过程:从 "**服务器证书**" 开始认证,**沿链条往上,直至根证书**。 > > 1. 服务器发送其 "**服务器证书**" & "**中间 CA 证书**"; > 2. 客户端根据 "**服务器证书**" 中的 "Issuer" 字段获取其**签发者**,用对应的 **"==中间 CA 证书==" 上的公钥**来验证 "**服务器证书**"; > 3. 依次类推,若存在多个中间 CA 证书,则对 "**当前中间 CA 证书**" 再用其 "**上级中间 CA 证书**" 上的公钥进行验证。 > 4. 最后,客户端用其内置的 **"==根 CA 证书==" 上的公钥** 验证 "**==最后一级中间 CA 证书==**" 的签名。 > > [!example] 证书认证链示意 > > ![[_attachment/02-开发笔记/07-计算机网络/传输层/SSL & TLS 协议.assets/IMG-SSL & TLS 协议-DC402568495334392F3CF9101219B981.png|621]] > > 示例:chrome 查看百度的服务器证书(三层), > > ![[_attachment/02-开发笔记/07-计算机网络/传输层/SSL & TLS 协议.assets/IMG-SSL & TLS 协议-96BEE420E22DE7DC16ED3736AB14C8FF.png|431]] > <br> ## 证书查看 > [!example] chrome 中查看网站的 "服务器证书" > ![[_attachment/02-开发笔记/07-计算机网络/传输层/SSL & TLS 协议.assets/IMG-SSL & TLS 协议-6304B5BB6AFEF6DF33F8726126DF5742.png|779]] > [!NOTE] Chrome 下查看浏览器导入的 "**根证书**" > > `chrome://settings/certificates` > > ![[_attachment/02-开发笔记/07-计算机网络/传输层/SSL & TLS 协议.assets/IMG-SSL & TLS 协议-41A7A0B2870CD1A66E08C8FEDAA1F9C7.png|774]] > [!NOTE] Windows 下查看 OS 内置的 "**==根证书==**" > > cmd 下执行命令: `certmgr.msc`,打开界面 > > ![[_attachment/02-开发笔记/07-计算机网络/传输层/SSL & TLS 协议.assets/IMG-SSL & TLS 协议-97ABAB1C2498BCDEAA679B48E2345AA7.png|721]] <br><br> # TLS 指纹 #TODO <br><br> # 参考资料 - [3.1 HTTP 常见面试题 | 小林coding](https://xiaolincoding.com/network/2_http/http_interview.html#http-3-%E5%81%9A%E4%BA%86%E5%93%AA%E4%BA%9B%E4%BC%98%E5%8C%96) - [HTTP 1.0 和 2.0 有什么区别? - 计算机网络面试题 - 面试鸭 - 程序员求职面试刷题神器](https://www.mianshiya.com/bank/1790948499480616961/question/1780933295710695425#heading-9) - [理解SSL/TLS系列 (四) 记录协议\_记录层-CSDN博客](https://blog.csdn.net/zhanyiwp/article/details/105627799) # Footnotes