TLS 四次握手详解
1. 客户端 Hello(Client Hello)
客户端向服务器发送 "Client Hello" 消息,内容包括:
- TLS 版本:客户端支持的最高 TLS 版本(例如 TLS 1.2 或 TLS 1.3)。
- 加密套件列表:客户端支持的一组加密算法,包括对称加密算法(如 AES)、哈希算法(如 SHA)以及公钥加密算法(如 RSA、ECDHE)。
- 随机数(Client Random):客户端生成的一个随机数,用于之后的密钥生成。
- 扩展信息:包括 SNI(Server Name Indication)等可选信息,用于支持多个主机托管在同一个 IP 地址上。
2. 服务器 Hello(Server Hello)
服务器在接收到客户端的 "Hello" 消息后,服务器发送 "Server Hello" 消息,内容包括:
- 协议版本:服务器选择的 TLS 版本(如果与客户端支持的版本兼容)。
- 加密套件:服务器选择的加密套件,用于后续通信的加密。
- 随机数(Server Random):服务器生成的一个随机数,也用于之后的密钥生成。
- 服务器证书:服务器发送自己的数字证书,用于验证服务器的身份。这个证书包含服务器的公钥,由可信的证书颁发机构(CA)签名。
- 密钥交换信息:如果服务器使用的是 ECDHE 或 DHE 这样的密钥交换算法,服务器还会发送公钥参数或 Diffie-Hellman 参数,以便生成共享的对称密钥。
- 可选信息:服务器可能会发送如会话 ID、压缩算法等附加信息。
3. 客户端密钥交换(Client Key Exchange)
在收到服务器的响应并验证证书后,客户端执行密钥交换过程,并发送以下内容:
- 前主密钥(Pre-master secret):客户端生成一个前主密钥(Pre-master Secret),并使用服务器的公钥对其进行加密。只有服务器可以用自己的私钥解密这个前主密钥。该密钥将用于生成主密钥,进而用于对称加密通信。
- 握手密钥生成:客户端和服务器根据之前交换的两个随机数(Client Random 和 Server Random)以及前主密钥,生成会话密钥(Session Key),用于加密接下来的数据传输。这个密钥是通过双方共同的算法和数据生成的,是对称加密密钥。
4. 握手结束
握手的最后阶段,双方互相通知对方加密通信已经准备就绪:
- 客户端 "Finished" 消息:客户端使用之前协商的对称密钥对一条 "Finished" 消息进行加密并发送。这条消息用于验证握手的完整性,同时也是客户端对加密通信的第一条消息。
- 服务器 "Finished" 消息:服务器也使用相同的对称密钥加密并发送一条 "Finished" 消息,确认握手成功并进入加密通信阶段。
SSL/TLS 握手的全部步骤
-
客户端 Hello(Client Hello)
- 客户端向服务器发送
Client Hello
消息,包含以下信息:- 支持的 SSL/TLS 版本(例如 TLS 1.2 或 TLS 1.3)
- 支持的加密套件(cipher suites)
- 支持的压缩方法(compression methods)
- 客户端生成的随机数(client random)
- 会话 ID(如
- V果是重新连接)
- 客户端向服务器发送
-
服务器 Hello(Server Hello)
- 服务器响应
Client Hello
,发送Server Hello
消息,包含以下信息:- 服务器选择的 SSL/TLS 版本
- 服务器选择的加密套件
- 服务器选择的压缩方法
- 服务器生成的随机数(server random)
- 会话 ID(如果是重新连接)
- 服务器响应
-
服务器证书(Server Certificate)
- 服务器发送其数字证书(包含公钥和由 CA 签名的信息)给客户端。这是用于客户端验证服务器身份的重要步骤。
-
服务器密钥交换(Server Key Exchange)
- 如果服务器选择的加密套件需要额外的密钥交换信息(例如使用 Diffie-Hellman 密钥交换),服务器会发送密钥交换消息。这包括服务器生成的密钥交换参数。
-
服务器 Hello Done
- 服务器发送
Server Hello Done
消息,标志着服务器端的握手消息发送完毕。
- 服务器发送
-
客户端证书(Client Certificate)
- 如果服务器要求客户端进行身份验证,客户端会发送其数字证书。此步骤是可选的,取决于服务器的要求。
-
客户端密钥交换(Client Key Exchange)
- 客户端生成一个预主密钥(pre-master secret),用服务器的公钥加密后发送给服务器。这个密钥用于生成会话密钥。
-
证书验证(Certificate Verify)
- 如果客户端提供了证书,它会用私钥对之前的所有握手消息进行签名,证明其身份。
-
客户端 Finished
- 客户端发送
Change Cipher Spec
消息,通知服务器后续消息将使用协商的加密套件进行加密。接着发送Finished
消息,验证之前的握手消息没有被篡改。
- 客户端发送
-
服务器 Finished
- 服务器收到客户端的
Finished
消息后,发送Change Cipher Spec
消息,通知客户端服务器也将使用协商的加密套件进行加密通信。接着发送Finished
消息,验证握手过程中的消息没有被篡改。
- 服务器收到客户端的
-
数据传输
- 握手完成后,客户端和服务器使用协商的会话密钥进行加密数据传输。
密钥的组成、生成及验证
1. 预主密钥的生成和使用
-
生成: 预主密钥(pre-master secret)是由客户端生成的一个随机值。在客户端的密钥交换消息中,客户端生成一个随机的预主密钥,并使用服务器的公钥对其进行加密。加密后的预主密钥被发送给服务器。
-
解密: 服务器使用其私钥解密预主密钥,恢复原始值。
2. 会话密钥的生成
- 生成: 会话密钥由客户端和服务器基于预主密钥和握手过程中交换的随机数(client random 和 server random)生成。具体步骤如下:
- 使用伪随机函数(PRF, Pseudo-Random Function),该函数通常基于哈希函数(如 SHA-256)和密钥派生函数(KDF)。
- PRF 输入包括:预主密钥、客户端和服务器生成的随机数。
- PRF 输出是多个会话密钥,包括对称加密密钥、消息认证码(MAC)密钥和初始化向量(IV)。
3. 会话密钥的验证
- 验证握手消息: 客户端和服务器在握手的最后阶段通过
Finished
消息来验证会话密钥。Finished
消息的内容是对握手过程中所有消息的哈希值(使用会话密钥加密)。这样可以确保握手过程没有被篡改。- 客户端和服务器都会计算
Finished
消息,并进行比对。如果计算出的Finished
消息一致,则表明握手过程没有被篡改,且会话密钥生成正确。
- 客户端和服务器都会计算
总结
对于开发者而言,虽然 SSL/TLS 握手过程的细节和密钥管理是透明的,但了解这些过程有助于理解 HTTPS 的安全性,帮助识别和解决可能的安全问题。在实际应用中,SSL/TLS 握手由库或框架处理,开发者通常只需要关注配置和调试,而无需直接操作握手过程的各个步骤。