跳过正文
  1. 2026s/

TLS非对称加密流程详解:从握手到对称加密通信

x
作者
x
熟练掌握Spring Boot、Spring Cloud等Java技术栈,专注于分布式系统设计与微服务架构。热爱技术分享,探索编程之美。
目录

TLS非对称加密流程详解:从握手到对称加密通信
#

TLS(Transport Layer Security,传输层安全协议)是互联网上最广泛使用的安全协议之一,它为客户端和服务器之间的通信提供了加密、身份验证和数据完整性保护。本文将详细介绍TLS握手过程中客户端和服务端的具体操作,包括CA证书验证、密钥交换,直到最终生成AES对称加密密钥进行正常通信的完整流程。

一、TLS概述
#

TLS协议的核心思想是:使用非对称加密进行身份验证和密钥交换,然后使用对称加密进行实际的数据传输。这样做的原因是:

  • 非对称加密(如RSA、ECDHE):安全性高,可以进行身份验证和安全的密钥交换,但计算开销大,速度慢
  • 对称加密(如AES):速度快,效率高,但需要双方提前共享密钥

TLS巧妙地结合了两者的优势:用非对称加密来安全地交换对称密钥,然后用对称密钥来加密实际的通信数据。

二、TLS握手完整流程
#

TLS握手是一个复杂但精妙的过程,主要使用TLS 1.2和TLS 1.3版本。这里我们以更常见的TLS 1.2为例进行详细说明。

2.1 第一步:客户端发送Client Hello
#

客户端的操作:

当用户在浏览器中访问一个HTTPS网站时,客户端(浏览器)首先发起TLS握手,向服务器发送一个"Client Hello"消息。

Client Hello包含的信息:

  1. TLS版本号:客户端支持的最高TLS版本(如TLS 1.2、TLS 1.3)
  2. 客户端随机数(Client Random):一个28字节的随机数,用于后续生成会话密钥
  3. 会话ID:如果是重新连接之前的会话,可以复用会话ID快速恢复
  4. 支持的加密套件列表(Cipher Suites):客户端支持的加密算法组合,例如:
    • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    • TLS_RSA_WITH_AES_256_CBC_SHA
  5. 支持的压缩方法:一般为null(不压缩)
  6. 扩展字段:如SNI(服务器名称指示)、支持的椭圆曲线、签名算法等
客户端 -> 服务器
Client Hello:
- TLS Version: 1.2
- Client Random: [28字节随机数]
- Cipher Suites: [加密套件列表]
- Extensions: SNI=example.com, ...

2.2 第二步:服务器响应Server Hello及证书
#

服务器的操作:

服务器收到Client Hello后,会进行以下操作:

2.2.1 发送Server Hello
#

服务器从客户端提供的加密套件列表中选择一个它支持且认为最安全的加密套件,并发送"Server Hello"消息。

Server Hello包含的信息:

  1. 选定的TLS版本:服务器选择的TLS版本(不高于客户端支持的版本)
  2. 服务器随机数(Server Random):另一个28字节的随机数,与Client Random一起用于生成会话密钥
  3. 选定的加密套件:从客户端列表中选择的一个加密套件
  4. 会话ID:服务器分配的会话ID,用于会话复用
  5. 扩展字段:对客户端扩展的响应
服务器 -> 客户端
Server Hello:
- TLS Version: 1.2
- Server Random: [28字节随机数]
- Selected Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- Session ID: [会话标识]

2.2.2 发送服务器证书(Certificate)
#

服务器发送它的数字证书链给客户端。证书链通常包括:

  1. 服务器证书:包含服务器的公钥、域名、有效期等信息
  2. 中间证书:一个或多个CA(证书颁发机构)的中间证书
  3. 根证书:(可选)根CA证书,通常客户端已经预装了受信任的根证书

证书中的关键信息:

Certificate:
- 版本号:V3
- 序列号:唯一标识
- 签名算法:SHA256-RSA
- 颁发者(Issuer):CA的名称
- 有效期:Not Before / Not After
- 主体(Subject):CN=example.com
- 主体公钥信息:
  - 公钥算法:RSA 2048位
  - RSA公钥:[服务器的公钥]
- CA签名:[CA用私钥对证书信息的签名]

2.2.3 发送Server Key Exchange(可选)
#

如果选择的加密套件使用了ECDHE(椭圆曲线迪菲-赫尔曼密钥交换)等需要额外密钥交换参数的算法,服务器会发送Server Key Exchange消息。

对于ECDHE_RSA加密套件:

服务器会:

  1. 生成一个临时的ECDHE密钥对(椭圆曲线公私钥)
  2. 发送ECDHE公钥参数给客户端
  3. 使用服务器证书的RSA私钥对这些参数进行签名,确保参数的真实性
Server Key Exchange:
- EC Curve Type: named_curve
- Named Curve: secp256r1
- EC Point (服务器ECDHE公钥): [公钥数据]
- Signature Algorithm: RSA-SHA256
- Signature: [用服务器RSA私钥签名]

2.2.4 发送Server Hello Done
#

服务器发送"Server Hello Done"消息,表示服务器的握手消息已经发送完毕。

服务器 -> 客户端
Server Hello Done

2.3 第三步:客户端验证证书(CA验证)
#

客户端的操作:

这是TLS安全性的核心环节之一。客户端收到服务器证书后,需要验证证书的真实性和有效性。

2.3.1 证书链验证过程
#

步骤1:检查证书的基本信息

  1. 域名验证:检查证书中的CN(Common Name)或SAN(Subject Alternative Name)是否与访问的域名匹配
  2. 有效期验证:检查当前时间是否在证书的有效期内(Not Before <= 当前时间 <= Not After)
  3. 证书用途验证:检查证书的扩展字段,确认证书可以用于TLS服务器身份验证

步骤2:验证证书签名(构建信任链)

这是最关键的步骤,客户端需要验证证书确实是由受信任的CA签发的:

  1. 获取颁发者证书:从证书链中获取颁发当前证书的CA证书(中间证书)
  2. 验证签名
    - 提取服务器证书中的签名值
    - 使用CA证书中的公钥解密签名
    - 对服务器证书的主体信息进行相同的哈希计算
    - 比较解密后的值与计算的哈希值是否一致
  3. 递归验证:对CA证书重复上述过程,直到找到一个客户端预装的受信任根证书
  4. 检查吊销状态:通过CRL(证书吊销列表)或OCSP(在线证书状态协议)检查证书是否被吊销

验证流程示例:

服务器证书 (CN=example.com)
  ↓ 验证签名
中间CA证书 (CN=Intermediate CA)
  ↓ 验证签名
根CA证书 (CN=Root CA) ← 客户端预装的受信任根证书

步骤3:验证Server Key Exchange签名(如果存在)

如果服务器发送了Server Key Exchange消息,客户端需要:

  1. 使用服务器证书中的公钥验证Server Key Exchange中的签名
  2. 确认ECDHE参数确实来自服务器,没有被中间人篡改

如果任何一步验证失败,客户端会中止连接并显示证书错误。

2.4 第四步:客户端发送Client Key Exchange
#

客户端的操作:

证书验证通过后,客户端需要生成用于对称加密的密钥材料。根据选择的加密套件不同,操作也不同。

2.4.1 RSA密钥交换方式
#

如果使用RSA密钥交换(如TLS_RSA_WITH_AES_128_CBC_SHA):

  1. 生成预主密钥(Pre-Master Secret):客户端生成一个48字节的随机数
  2. 加密预主密钥:使用服务器证书中的RSA公钥加密Pre-Master Secret
  3. 发送Client Key Exchange:将加密后的Pre-Master Secret发送给服务器
客户端 -> 服务器
Client Key Exchange:
- Encrypted Pre-Master Secret: [RSA公钥加密的48字节随机数]

服务器收到后,使用自己的RSA私钥解密,获得Pre-Master Secret。

2.4.2 ECDHE密钥交换方式(推荐)
#

如果使用ECDHE密钥交换(如TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256):

  1. 生成客户端ECDHE密钥对:客户端生成一个临时的椭圆曲线密钥对
  2. 计算共享密钥(Pre-Master Secret):使用客户端的ECDHE私钥和服务器的ECDHE公钥,通过椭圆曲线Diffie-Hellman算法计算出Pre-Master Secret
  3. 发送Client Key Exchange:将客户端的ECDHE公钥发送给服务器
客户端 -> 服务器
Client Key Exchange:
- EC Point (客户端ECDHE公钥): [公钥数据]

服务器收到后,使用自己的ECDHE私钥和客户端的ECDHE公钥,计算出相同的Pre-Master Secret。

ECDHE的优势:

  • 前向保密(Perfect Forward Secrecy, PFS):即使服务器私钥泄露,之前的会话也无法被解密,因为每次握手使用的ECDHE密钥对都是临时的

2.5 第五步:生成会话密钥(Master Secret和对称密钥)
#

此时,客户端和服务器都拥有三个关键数据:

  1. Client Random:客户端生成的随机数
  2. Server Random:服务器生成的随机数
  3. Pre-Master Secret:通过密钥交换得到的共享密钥

双方独立进行相同的计算:

2.5.1 生成Master Secret
#

使用伪随机函数(PRF)结合上述三个值生成48字节的Master Secret:

Master Secret = PRF(Pre-Master Secret, "master secret", Client Random + Server Random)

PRF通常使用HMAC-SHA256或HMAC-SHA384,确保生成的密钥具有足够的随机性和安全性。

2.5.2 生成会话密钥
#

从Master Secret中派生出实际用于加密的密钥材料,包括:

  1. 客户端写入密钥(Client Write Key):客户端加密数据用的AES密钥
  2. 服务器写入密钥(Server Write Key):服务器加密数据用的AES密钥
  3. 客户端写入MAC密钥:客户端计算消息认证码用的密钥
  4. 服务器写入MAC密钥:服务器计算消息认证码用的密钥
  5. 客户端IV(初始化向量):客户端加密用的初始化向量
  6. 服务器IV:服务器加密用的初始化向量

对于使用AES-128-GCM的加密套件,密钥生成如下:

Key Block = PRF(Master Secret, "key expansion", Server Random + Client Random)

从Key Block中依次提取:
- Client Write MAC Key: 0字节(GCM模式不需要单独的MAC密钥)
- Server Write MAC Key: 0字节
- Client Write Key: 16字节(AES-128)
- Server Write Key: 16字节(AES-128)
- Client Write IV: 4字节(GCM的固定IV部分)
- Server Write IV: 4字节

至此,双方都拥有了相同的对称加密密钥(AES密钥),但客户端和服务器使用不同的密钥对来加密各自发送的数据,确保双向通信的独立性和安全性。

2.6 第六步:客户端发送Change Cipher Spec和Finished
#

客户端的操作:

2.6.1 发送Change Cipher Spec
#

客户端发送一个"Change Cipher Spec"消息,通知服务器:“从现在开始,我发送的消息将使用刚才协商好的加密算法和密钥进行加密。”

客户端 -> 服务器
Change Cipher Spec

这是一个独立的协议消息(不属于握手协议),只有1个字节:0x01。

2.6.2 发送Encrypted Handshake Message (Finished)
#

客户端发送第一个加密的消息"Finished",其中包含:

  1. verify_data:对之前所有握手消息的哈希值,使用Master Secret计算出的校验数据
verify_data = PRF(Master Secret, "client finished", 
                  Hash(所有之前的握手消息))

这个Finished消息是使用刚才生成的对称密钥(AES)加密的。

客户端 -> 服务器
[加密的] Handshake: Finished

目的:

  • 验证密钥派生正确
  • 验证握手消息没有被篡改
  • 确认加密机制正常工作

2.7 第七步:服务器发送Change Cipher Spec和Finished
#

服务器的操作:

2.7.1 验证客户端的Finished消息
#

服务器收到客户端的加密Finished消息后:

  1. 使用协商好的对称密钥(Server Write Key的对应解密密钥)解密消息
  2. 计算自己的verify_data,与客户端发送的进行比对
  3. 如果一致,说明密钥协商成功,握手消息完整

2.7.2 发送Change Cipher Spec
#

服务器也发送"Change Cipher Spec"消息,通知客户端它也将开始使用加密通信。

服务器 -> 客户端
Change Cipher Spec

2.7.3 发送Encrypted Handshake Message (Finished)
#

服务器发送加密的Finished消息:

verify_data = PRF(Master Secret, "server finished", 
                  Hash(所有之前的握手消息))
服务器 -> 客户端
[加密的] Handshake: Finished

2.8 第八步:握手完成,开始加密通信
#

客户端的操作:

客户端收到服务器的Finished消息后:

  1. 解密并验证服务器的verify_data
  2. 如果验证成功,TLS握手完成

握手完成!

此时,客户端和服务器之间建立了安全的加密通道,双方都确认了:

  • 对方的身份(通过证书验证)
  • 握手消息的完整性(通过Finished消息)
  • 对称密钥协商成功(能够正确解密对方的消息)

从现在开始,所有的应用数据都将使用AES对称加密算法进行加密传输。

三、加密通信阶段
#

握手完成后,客户端和服务器使用协商好的对称密钥进行数据传输。

3.1 应用数据加密
#

以AES-128-GCM模式为例:

客户端发送数据:

原始数据:GET /api/users HTTP/1.1
         Host: example.com
         ...

加密过程:
1. 使用Client Write Key(AES-128密钥)
2. 使用Client Write IV和序列号生成唯一的nonce
3. 使用AES-GCM加密数据,生成密文和认证标签
4. 发送:TLS Record Header + 加密数据 + 认证标签

服务器接收并解密:

1. 使用Client Write Key解密
2. 验证认证标签,确保数据完整性和真实性
3. 获得原始HTTP请求

服务器发送响应:

原始数据:HTTP/1.1 200 OK
         Content-Type: application/json
         {"users": [...]}

加密过程:
1. 使用Server Write Key(AES-128密钥)
2. 使用Server Write IV和序列号生成唯一的nonce
3. 使用AES-GCM加密数据
4. 发送加密的响应

3.2 对称加密的特点
#

  • 速度快:AES加密速度远快于RSA,适合大量数据传输
  • 双向独立:客户端和服务器使用不同的密钥,即使一个方向的密钥泄露,另一个方向仍然安全
  • 完整性保护:GCM模式提供认证加密,不仅加密数据,还能检测篡改
  • 序列号保护:每个TLS记录都有序列号,防止重放攻击和乱序

四、TLS 1.3的改进
#

TLS 1.3简化了握手流程,提高了安全性和性能:

4.1 主要改进
#

  1. 减少往返次数:TLS 1.3只需1-RTT(往返时间)即可完成握手,TLS 1.2需要2-RTT
  2. 强制前向保密:移除了RSA密钥交换,只支持ECDHE等提供前向保密的算法
  3. 移除不安全算法:移除了RC4、3DES、MD5、SHA-1等已知有弱点的算法
  4. 简化加密套件:只保留5个加密套件,减少配置复杂度
  5. 加密更多握手消息:除了Client Hello和Server Hello,其他握手消息都加密
  6. 支持0-RTT:对于重新连接的会话,可以在第一次往返时就发送应用数据(有重放风险,需谨慎使用)

4.2 TLS 1.3握手简化流程
#

客户端                                服务器

Client Hello
+ Key Share (ECDHE公钥)
+ Supported Groups    -------->
                                    Server Hello
                                + Key Share (ECDHE公钥)
                      <-------- [加密] Certificate
                                [加密] Certificate Verify
                                [加密] Finished
[加密] Finished        -------->
[加密] Application Data <------> [加密] Application Data

密钥派生也简化为基于HKDF(HMAC-based Key Derivation Function)的单一密钥派生链。

五、安全性分析
#

5.1 TLS如何防止常见攻击
#

  1. 中间人攻击(MITM)

    • 通过CA证书验证确保服务器身份
    • Server Key Exchange签名防止参数被篡改
    • Finished消息验证握手完整性
  2. 重放攻击

    • 客户端和服务器的随机数确保每次会话密钥不同
    • TLS记录的序列号防止重放单个消息
  3. 降级攻击

    • Finished消息包含所有握手消息的哈希,任何篡改都会被检测到
    • TLS 1.3移除了不安全的加密套件
  4. 密钥泄露

    • ECDHE提供前向保密,即使服务器私钥泄露,之前的会话也无法解密

5.2 证书固定(Certificate Pinning)
#

对于高安全性需求的应用,可以使用证书固定:

  • 客户端预存服务器证书或公钥的哈希值
  • 连接时验证服务器证书是否匹配预存的值
  • 即使CA被攻破,攻击者也无法伪造证书

六、总结
#

TLS协议通过精妙的设计,实现了安全、高效的网络通信:

  1. 握手阶段(使用非对称加密):

    • 客户端发送Client Hello,包含支持的加密套件和随机数
    • 服务器响应Server Hello,选择加密套件并发送证书和随机数
    • 客户端验证证书(CA验证),构建信任链
    • 双方通过RSA或ECDHE交换Pre-Master Secret
    • 双方独立计算Master Secret和会话密钥
    • 双方发送Change Cipher Spec和加密的Finished消息确认
  2. 数据传输阶段(使用对称加密):

    • 使用协商好的AES密钥加密所有应用数据
    • 提供高速、安全的双向通信
    • 每个方向使用独立的密钥,增强安全性
  3. 安全保障

    • CA证书验证确保服务器身份真实性
    • 数字签名防止握手消息被篡改
    • 前向保密保护历史会话
    • 认证加密(如GCM)保证数据完整性

TLS协议是现代互联网安全的基石,理解其工作原理对于开发安全的网络应用至关重要。无论是电子商务、在线银行还是日常的Web浏览,TLS都在默默地保护着我们的数据安全和隐私。

通过邮件回复

相关文章

使用Debian作为路由器:完整配置指南

使用Debian作为路由器:完整配置指南 # 在企业环境或高级家庭网络中,使用Linux系统(特别是Debian)作为路由器可以提供更强大的功能、更高的灵活性和更好的性能。本文将详细介绍如何将Debian配置为功能完整的路由器,包括DHCP服务、DNS服务、NAT配置、IPv6中继、网桥设置等核心功能。

spring三级缓存介绍

6 分钟
Spring的三级缓存介绍 Spring框架在处理单例Bean的创建和依赖注入时,使用了三级缓存机制来管理Bean的生命周期和解决潜在的循环依赖问题。这些缓存主要定义在org.springframework.beans.factory.support.DefaultSingletonBeanRegistry类中。下面结合源码进行详细介绍。

Java GC进化路程

4 分钟
1. 概述 # 本博客中我们将展示不同JVM垃圾回收(GC)实现的基本原理。然后我们将学习如何在应用程序中启动特定类型的垃圾回收。

部署基于artalk的评论系统

1 分钟
部署基于artalk的评论系统 # 在现代博客和网站中,评论系统是与读者互动的重要工具。Artalk 是一个开源的评论系统,具有轻量级、易于集成和高度可定制的特点。本文将介绍如何在 Hugo 博客中部署基于 Artalk 的评论系统。

反转链表

反转链表 # 这是我写的算法可以用来参考,上边有测试用例可以用来检测代码写的对不对。

新时代之sing-box

新时代之sing-box:下一代通用代理平台 # sing-box 是一个通用的代理平台,支持多种协议,具有强大的路由功能和高性能表现。它是新一代的网络代理工具,相比传统的代理软件,sing-box 在功能性、性能和可配置性方面都有显著提升。