SSL/TLS 的握手流程是怎样的?
SSL/TLS 握手(Handshake)是 HTTPS 连接建立过程中最关键的一步。它的主要目的是在客户端(如浏览器)和服务器之间协商加密算法、验证身份,并生成用于后续通信的对称加密密钥(Session Key)。
目前主流的协议版本是 TLS 1.2 和 TLS 1.3。TLS 1.3 是最新标准,速度更快、更安全,但 TLS 1.2 依然广泛使用。
为了让你更容易理解,我们以经典的 TLS 1.2 为例进行详细拆解,最后再对比 TLS 1.3 的改进。
核心目标
握手过程主要为了达成以下共识:
- 加密套件:用什么算法加密?用什么算法校验数据完整性?
- 身份验证:服务器(有时候也包括客户端)是真的吗?(通过证书)
- 生成密钥:双方生成一个只有彼此知道的“会话密钥”(Session Key),用于后续的数据传输。
TLS 1.2 握手详细流程 (4次挥手类似,这里是4步主要交互)
可以将握手过程想象成两个人(爱丽丝和鲍勃)在商量怎么用暗号传纸条。
第一步:Client Hello(客户端打招呼)
客户端(浏览器)向服务器发起请求,发送以下信息:
- 支持的 TLS 版本:比如 TLS 1.2。
- 支持的加密套件列表(Cipher Suites):比如“我会 RSA、也会 ECDHE,还支持 AES-256...”。
- Client Random:一个随机数(这是生成最终密钥的第一个素材)。
第二步:Server Hello & Certificate(服务器回应 & 亮证)
服务器收到请求后,回复以下信息:
- 确定的 TLS 版本:比如“那我们就用 TLS 1.2 吧”。
- 选定的加密套件:比如“我们用 RSA 握手,用 AES-128 加密数据”。
- Server Random:服务器生成的另一个随机数(这是生成最终密钥的第二个素材)。
- Server Certificate(数字证书):包含服务器的公钥(Public Key)、域名信息、颁发机构(CA)签名等。
- (可选) 如果需要,服务器会发送 Server Key Exchange 消息(针对某些密钥交换算法)。
- Server Hello Done:告诉客户端“我说完了”。
第三步:验证证书 & Client Key Exchange(验证 & 交换秘密)
客户端收到证书后,会进行验证:
- 检查证书是否由受信任的 CA 颁发。
- 检查证书是否过期。
- 检查证书域名是否与访问的域名一致。
验证通过后,客户端开始生成密钥素材:
- 生成 Pre-Master Secret:客户端生成第三个随机数,称为“预主密钥”。
- 加密传输:客户端使用证书里的服务器公钥,对这个 Pre-Master Secret 进行加密,然后发送给服务器。
- 注意:因为只有服务器有私钥,所以只有服务器能解开这个包,拿到 Pre-Master Secret。
第四步:生成会话密钥 & Finished(生成密钥 & 握手结束)
现在,客户端和服务器手里都有了三样东西:
- Client Random
- Server Random
- Pre-Master Secret
双方使用相同的算法,将这三个参数混合,生成最终的 Master Secret(主密钥),进而衍生出 Session Key(会话密钥)。
- Client Finished:客户端发送一条消息“Change Cipher Spec”,表示“后面的消息我都用 Session Key 加密了”,并发送一段握手数据的 Hash 值供服务器校验。
- Server Finished:服务器解密并校验无误后,也发送“Change Cipher Spec”,表示“我也切换到加密模式”,并发送握手数据的 Hash 值。
握手完成! 此后双方的通信内容(HTTP 请求/响应)全部使用 Session Key 进行对称加密传输。
图解总结 (TLS 1.2)
plaintext
Client Server
| |
| (1) Client Hello (随机数1 + 支持的算法) |
|--------------------------------------------------->|
| |
| (2) Server Hello (随机数2 + 选定的算法) |
| Certificate (公钥) |
| Server Hello Done |
|<---------------------------------------------------|
| |
[验证证书] |
[生成随机数3(Pre-Master)] |
| |
| (3) Client Key Exchange (用公钥加密的随机数3) |
| Change Cipher Spec (准备切换加密) |
| Finished (加密的握手摘要) |
|--------------------------------------------------->|
| |
| [用私钥解密得到随机数3]
| [计算 Session Key]
| |
| (4) Change Cipher Spec (准备切换加密) |
| Finished (加密的握手摘要) |
|<---------------------------------------------------|
| |
[握手结束,建立安全通道] [握手结束]
| (使用 Session Key 加密传输数据) |
|<==================================================>|
TLS 1.3 的改进(更快、更安全)
TLS 1.2 虽然经典,但握手需要 2个 RTT(往返时间),速度较慢,且 RSA 密钥交换不支持“前向安全性”(如果私钥被偷,以前截获的流量都能被解密)。
TLS 1.3 做了巨大的优化:
- 1-RTT 握手:TLS 1.3 假设客户端和服务器会使用某种常用的密钥交换算法(如 ECDHE)。客户端在发送
Client Hello的同时,直接把密钥交换所需的参数(Key Share)一起发过去了。如果服务器支持,直接就能算出 Session Key。这样只用1个往返就能完成握手。 - 废除 RSA 密钥交换:强制使用 ECDHE 等算法,确保前向安全性(即使服务器私钥泄露,黑客也无法解密之前的历史数据)。
- 加密更早:Server Hello 之后的大部分握手消息已经是加密的了,防止隐私泄露。
总结
- 非对称加密(公钥/私钥):仅用于握手阶段,用来安全地交换“预主密钥”和验证身份。
- 对称加密(Session Key):用于握手完成后的数据传输,因为速度快。
- TLS 1.2:需要 2 个往返,流程清晰但稍慢。
- TLS 1.3:仅需 1 个往返,更快且更安全,是未来的主流。
右滑查看面试常问