%%
# 纲要
> 主干纲要、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