TLS协议梳理

    • HTTPS = HTTP + SSL(Secure Socket Layer)/TLS(Transport Layer Security), 在HTTP的基础上增加了SSL/TLS协议,用于加密和解密数据,确保数据传输的安全性,SSL是早期版本,现已被TLS取代,在浏览器中查看使用HTTPS的网站时,打开开发者工具,打开安全一栏,可以看到该网站使用的证书,tls版本和加密算法等

      • 第一个TLS版本,基于SSL 3.0开发

      • 主要特性:

        • 支持RSA和DH密钥交换

        • 支持RC4、DES等对称加密算法

        • 存在BEAST攻击等安全漏洞

      • 主要改进:

        • 增加了对CBC模式的保护

        • 增加了显式IV(初始化向量)

        • 修复了一些TLS 1.0的安全问题

      • 重要改进:

        • 支持更安全的加密套件(如AES-GCM)

        • 支持SHA-256等更强的哈希算法

        • 改进了PRF(伪随机函数)

        • 目前仍广泛使用

      • 重大改进:

        • 握手过程简化,只需1-RTT

        • 0-RTT恢复会话

        • 移除了不安全的加密算法

        • 前向安全性得到增强

        • 所有握手消息在ServerHello之后都加密

        • 移除了静态RSA和DH密钥交换

        • 目前是最新推荐版本

    • TLS协议分为上层协议和下层协议,上层协议包含握手协议,警报协议,应用数据协议,下次为记录层协议(Record Layer Protocol),记录层协议的主要作用如下

      • 分片: 将上层协议的数据分割成合适大小的块,每个块最大不超过 16KB

      • 封装: 为每个数据块添加头部信息,标识数据类型、协议版本和长度

      • 加密: 对每个数据块进行加密,确保数据传输的安全性

      • 记录层协议头格式

        • 每个 TLS 记录都以 5 字节的头部开始:

          |<- 1 ->|<------ 2 ------>|<----- 2 ---->|
          +--------+----------------+---------------+
          |  类型  |    版本号      |    长度      |
          +--------+----------------+---------------+
          • 类型(Type): 1 字节

            • 0x16: Handshake (握手)

            • 0x17: Application Data (应用数据)

            • 0x15: Alert (警告)

          • 版本号(Version): 2 字节

            • 0x0301: TLS 1.0

            • 0x0302: TLS 1.1

            • 0x0303: TLS 1.2/1.3

          • 长度(Length): 2 字节

            • 表示后续数据的长度

        • 示例:

          16 03 01 01 4a  // 第一个 ClientHello 的记录层头
          • 0x16: 表示这是握手消息

          • 0x0301: 表示 TLS 1.0 记录层版本

          • 0x014a: 表示后续数据长度为 330 字节

      • 注意:

        • TLS记录层协议的版本可以与握手协议中使用的版本不一致,这是TLS 1.3中的一个特别设计。这种设计主要是为了确保向后兼容性,让支持TLS 1.3的通信在网络中的其他设备(比如中间的代理或防火墙)仍然能够以TLS 1.2的方式处理TLS记录,即使实际的握手和数据传输使用的是TLS 1.3。

        • 在TLS 1.2及之前的版本中,记录层的版本号通常与握手使用的版本相匹配。但在TLS 1.3中,为了改进安全性和性能同时避免中间设备的干扰,引入了以下变化:

          • 记录层版本号:

            • 在TLS 1.3中,所有传出的记录(无论是握手还是数据传输)的版本号都被设定为0x0303(即TLS 1.2),即使实际的握手使用的是TLS 1.3。

          • 握手协议的版本:

            • 握手协议的真正版本是通过ClientHelloServerHello消息中的supported_versions扩展来指定的。这个扩展允许客户端和服务器协商实际要使用的最高TLS版本,包括TLS 1.3。

    • 握手阶段涉及的加密算法

        • 基本原理:私钥加密,公钥验证

        • RSA(Rivest-Shamir-Adleman)算法

          • 对应RSA证书

          • 兼容性好,广泛使用

          • 密钥长度长,性能一般,常见密钥长度: 2048位(当前最低推荐长度), 3072位, 4096位(更高安全性)

          • 签名填充方案对比

            特性
            PKCS v1.5 签名
            RSA-PSS

            用途

            数字签名

            数字签名

            安全性

            较弱(缺乏可证明安全性)

            强(可证明安全)

            填充结构

            sd

            使用盐值和MGF

            随机性

            确定性(相同消息产生相同签名)

            概率性(相同消息产生不同签名)

            现代协议支持

            广泛支持(传统系统)

            TLS 1.3唯一支持的RSA方案

            性能

            较快

            较慢

            推荐使用

            仅用于兼容性

            推荐

        • ECDSA(Elliptic Curve Digital Signature Algorithm)算法

          • 对应ECC证书

          • 是一种基于椭圆曲线的数字签名算法

          • 性能好,密钥长度短,适合移动设备、物联网设备等资源受限环境下的应用场景

        • PSK(Pre-Shared Key)

          • 最简单的方式双方提前约定好密钥,后续通信时直接使用这个密钥

          • TLS1.3中的PSK指的是上次连接生成的PSK,客户端保存后,用于下次0RTT传输

        • RSA

          • 使用RSA算法进行密钥交换, 客户端使用公钥加密,服务端使用私钥解密

            • 加密填充方案对比

              特性
              PKCS v1.5 加密
              PKCS OAEP

              用途

              数据加密

              数据加密

              安全性

              较弱(易受Bleichenbacher攻击)

              强(可证明安全)

              填充结构

              使用双重掩码(MGF)

              随机性

              部分随机(PS部分)

              完全随机

              现代协议支持

              逐渐淘汰

              广泛支持

              性能

              较快

              较慢

              推荐使用

              不推荐

              推荐

            • RSA 模式有一个严重的缺点:它不是前向保密的。这意味着如果有人记录了加密的对话,然后获取了服务器的 RSA 私钥,他们就可以解密对话。即使对话是在很久以前记录的,而密钥是在未来某个时间获得的,这也适用

            • tls1.3中不再支持RSA密钥交换算法

        • DH(Diffie-Hellman)

          • DH基于大整数分解问题(Discrete Logarithm Problem),DH协议允许通信双方在不安全的通信通道上协商一个共享的对称密钥,DH生成的密钥通常是长期有效的,它不是前向保密的

          • 客户端和服务器首先各自创建一个公私钥对。然后,它们将公钥部分发送给对方。当每一方收到对方的公钥部分后,将其与自己的私钥结合,最终得到相同的值:预主密钥

          • 原理可以想象成调配颜料的过程:

              1. 爱丽丝和鲍勃先约定使用黄色作为基础颜色(公钥)

              1. 爱丽丝秘密选择红色,鲍勃秘密选择蓝色(这是各自的私钥)

              1. 爱丽丝将黄色+红色混合,把结果发给鲍勃(KeyExchange)

              1. 鲍勃将黄色+蓝色混合,把结果发给爱丽丝(KeyExchange)

              1. 爱丽丝将收到的(黄+蓝)再加入红色

              1. 鲍勃将收到的(黄+红)再加入蓝色

              1. 最终双方都得到了相同的紫色(黄+红+蓝),这就是共享密钥

          • Diffie-Hellman 的安全性依赖于一个称为离散对数问题的特定数学难题的难度。如果能为一组参数解决离散对数问题,就可以提取私钥并破坏协议的安全性。一般来说,使用的数字越大,解决离散对数问题就越困难。因此,如果选择了较小的 DH 参数,则可能存在安全风险。TLS 1.3 取消了这一选择权,只保留了几种固定的DH参数,这些参数是经过广泛测试和验证的,安全性较高

        • DHE(Diffie-Hellman Ephemeral)

          • DHE是DH的改进版本,DHE生成的密钥是临时有效的,每次握手都会生成新的密钥,提供前向安全性

        • ECDH(Elliptic Curve Diffie-Hellman)

          • ECDH是基于椭圆曲线密码学的密钥交换协议,和DH原理基本相同,在相同的密钥强度下比DH更加高效。ECDH生成的密钥通常是长期有效的,因此安全性依赖于长期保持私密性

        • ECDHE(Elliptic Curve Diffie-Hellman Ephemeral)

          • ECDHE是ECDH的改进版本,ECDHE生成的密钥是临时有效的,每次握手都会生成新的密钥,提供前向安全性

        • 关于静态密钥和临时密钥

          • 服务端证书包含固定DH参数,客户端使用使用证书中的参数,双方计算共享密钥,每次会话都使用相同的参数,称为静态密钥

          • 服务端生成新的DH参数,将参数发送给客户端,客户端生成自己的密钥对,双方交换公钥并计算共享密钥,每次会话都使用新的DH参数

          • TLS1.3不再支持静态密钥交换算法,只支持临时密钥交换算法,包括ECDHE,有限DHE, 所有的密钥交换算法都提供前向安全性. 支持的身份验证算法为: RSA-PSS(最小密钥长度2048位),ECDSA,EdDSA

        • 握手成功后,客户端使用对称加密算法加密,服务端解密

        • 对称密码分为两种主要形式:

          • 流密码(Stream Cipher)

            • 工作原理:

              • 使用固定大小的密钥生成任意长度的密钥流(伪随机数据流)

              • 加密时将消息与密钥流按位异或

              • 解密时将密文与密钥流按位异或

            • 工作原理详解:

              • 加密和解密过程:

                • 加密: 明文 P 与密钥 K 进行异或操作,生成密文 C :

                  • C = P ⊕ K

                • 解密: 密文 C 与密钥 K 再次异或,恢复明文 P :

                  • C ⊕ K = (P ⊕ K) ⊕ K = P ⊕ (K ⊕ K) = P ⊕ 0 = P

              • 异或操作的核心特性:

                • 自反性: A ⊕ A = 0

                  • 任何值与自身异或结果为0

                • 与0的关系: A ⊕ 0 = A

                  • 任何值与0异或结果是其本身

                • 可逆性: (A ⊕ B) ⊕ B = A

                  • 异或操作可逆,两次异或同一个值会恢复原始值

              • 举例说明:

                • 明文 P = 1010

                • 密钥 K = 1100

                • 加密: C = P ⊕ K = 1010 ⊕ 1100 = 0110

                • 解密: P = C ⊕ K = 0110 ⊕ 1100 = 1010

            • 特点:

              • 实现简单

              • 软件中运行速度快

              • 适合实时加密

            • 代表算法:

              • RC4

              • ChaCha20

          • 分组密码(Block Cipher)

            • 工作原理:

              • 只能加密固定大小的数据块

              • 对于短于分组大小的消息需要填充

              • 对于长于分组大小的消息需要分块处理

            • CBC模式工作原理:

              • 加密过程:

                  1. 将明文分成固定大小的块(如128位)

                  1. 生成随机的初始化向量(IV)

                  1. 对每个明文块:

                  2. 将当前明文块与前一个密文块(或IV)进行异或

                  3. 对异或结果进行加密,得到当前密文块

                  1. 将所有密文块连接形成完整密文

              • 解密过程:

                  1. 将密文分成固定大小的块

                  1. 对每个密文块:

                  2. 对当前密文块进行解密

                  3. 将解密结果与前一个密文块(或IV)异或,恢复明文块

                  1. 将所有明文块连接形成完整明文

              • 举例说明:

                • 假设使用AES-128加密:

                  • 明文: HELLO WORLD!1234 (16字节)

                  • 密钥: 0123456789ABCDEF (16字节)

                  • IV: FEDCBA9876543210 (16字节)

                • 加密过程:

                  • 明文块与IV异或: HELLO WORLD!1234 XOR FEDCBA9876543210 = 结果1

                  • 对结果1进行AES加密得到密文块

                • 解密过程:

                  • 对密文块AES解密得到结果1

                  • 结果1与IV异或: 结果1 XOR FEDCBA9876543210 = HELLO WORLD!1234

              • 特点:

                • 需要初始化向量(IV)

                • 每个明文块的加密依赖于前一个密文块

                • 需要填充(Padding)确保明文长度是分组大小的整数倍

                • 通过链式结构增强加密随机性和安全性

            • 常用模式:

              • CBC(Cipher Block Chaining)模式

                • 每个明文块先与前一个密文块异或后再加密

            • 代表算法:

              • AES

              • DES

              • 3DES

        • 散列函数的特性

          • 无法从散列值反推原文

          • 难以找到两个不同的输入产生相同的散列值

          • 固定长度输出

        • 散列函数在TLS中主要用于:

          • 数字签名生成和验证

            • 签名时使用散列的原因是:

              • 哈希值长度固定,处理更快

              • 减少签名运算的数据量

              • 适合任意长度的输入数据

              • 保证数据完整性

              • 克服了RSA等算法的长度限制

              type DigitalSigner struct {
              	privateKey *rsa.PrivateKey
              	publicKey  *rsa.PublicKey
              }
              
              // 签名数据
              func (ds *DigitalSigner) SignData(data []byte) ([]byte, error) {
              	// 1. 计算数据的哈希值
              	hashed := sha256.Sum256(data)
              	
              	// 2. 生成签名
              	signature, err := rsa.SignPKCS1v15(
              		rand.Reader,
              		ds.privateKey,
              		crypto.SHA256,
              		hashed[:],
              	)
              	if err != nil {
              		return nil, err
              	}
              	
              	return signature, nil
              }
              
              // 验证签名
              func (ds *DigitalSigner) VerifySignature(data, signature []byte) error {
              	// 1. 计算数据的哈希值
              	hashed := sha256.Sum256(data)
              	
              	// 2. 验证签名
              	return rsa.VerifyPKCS1v15(
              		ds.publicKey,
              		crypto.SHA256,
              		hashed[:],
              		signature,
              	)
              }
          • 消息认证码(HMAC)生成

            • 提供消息完整性和认证

            • 配合时间戳和过期机制可以防止重放攻击

            • MAC-then-Encrypt 和 Encrypt-then-MAC

              • MAC-then-Encrypt(TLS1.2及以前):

                • 先计算明文的MAC,再加密明文和MAC

                • 存在安全隐患:

                  • 接收方需要先解密才能验证MAC

                  • 容易受到填充oracle攻击(如POODLE)

                  • MAC验证滞后,攻击者可在解密过程中攻击

              • Encrypt-then-MAC(TLS1.3):

                • 先加密明文,再计算密文的MAC

                • 更安全的原因:

                  • 接收方先验证MAC,确保密文未被篡改

                  • MAC验证失败直接拒绝,无需解密

                  • 避免了填充oracle攻击

              • 举例说明

                • 假设明文为HELLO,密钥为KEY_ENC和KEY_MAC

                • MAC-then-Encrypt流程:

                    1. 计算MAC: MAC(HELLO)得到MAC_HELLO

                    1. 拼接: HELLO || MAC_HELLO

                    1. 加密得到密文

                • Encrypt-then-MAC流程:

                    1. 加密HELLO得到密文

                    1. 计算密文的MAC

                    1. 发送密文||MAC

        • 伪随机数生成

        • 密钥导出

        • 常见的散列函数包括:

          • MD5(已不安全,不推荐使用)

          • SHA-1(已不安全,不推荐使用)

          • SHA-2家族(SHA-256/384/512)

          • SHA-3家族

          • 密钥交换

            • 通过RSA或Diffie-Hellman等密钥交换算法生成预主密钥(Pre-Master Secret)

          • 生成主密钥

            • 使用预主密钥、客户端随机数和服务器随机数

            • 通过PRF(基于HMAC-SHA256的伪随机函数)生成主密钥(Master Secret)

          • 派生会话密钥 从主密钥中派生出用于加密和完整性检查的密钥块,包括:

            • 客户端写加密密钥(Client Write Encryption Key)

            • 服务器写加密密钥(Server Write Encryption Key)

            • 客户端写MAC密钥(Client Write MAC Key)

            • 服务器写MAC密钥(Server Write MAC Key)

            • 加密模式(如CBC)所需的IV(初始化向量)

        • (EC)DHE 密钥交换
          
          Shared Secret
          
          Early Secret (可选,用于 0-RTT)
          
          Handshake Secret (握手密钥)
          
          Master Secret (主密钥)

          握手阶段密钥

          • Client Handshake Traffic Secret

          • Server Handshake Traffic Secret

        • 应用数据密钥

          • Client Application Traffic Secret

          • Server Application Traffic Secret

        • 特殊用途密钥

          • Resumption Master Secret (会话恢复主密钥))

              Master Secret
            
              HKDF-Expand-Label(
                secret: Master Secret,
                label: "res master",
                context: Transcript-Hash(Handshake Context),
                length: Hash.length
              )
            
              Resumption Master Secret
            • 用途:

              • 生成 PSK (Pre-Shared Key),用于下一次连接

              • 支持会话恢复

              • 启用 0-RTT 数据传输

          • Early Exporter Master Secret (早期导出主密钥)

            Early Secret
            
            HKDF-Expand-Label(
                secret: Early Secret,
                label: "e exp master",
                context: Transcript-Hash(Handshake Context),
                length: Hash.length
            )
            
            Early Exporter Master Secret
            • 用途:

              • Early Exporter Master Secret 是保护 0-RTT 数据的工具

              • 它在 0-RTT 传输过程中使用,提供额外的安全保证

          • Exporter Master Secret (用于外部密钥导出)

            Master Secret
            
            HKDF-Expand-Label(
                secret: Master Secret,
                label: "exp master",
                context: Transcript-Hash(Handshake Context),
                length: Hash.length
            )
            
            Exporter Master Secret
            • 用途

              • 为外部协议提供密钥材料

              • 支持协议绑定

              • 派生额外的密钥

        • 密钥交换: X25519

          • 是ECDHE的特定实现,专门使用Curve25519曲线,无需协商曲线

          • 固定32字节密钥长度

        • 对称加密: AES-256-GCM

          • AES-256表示使用256位密钥的高级加密标准

          • GCM(Galois/Counter Mode)是一种认证加密模式

            • 提供机密性、完整性和真实性保护

            • 支持并行处理,性能优秀

            • 不需要额外的消息认证码(MAC)

        • 散列函数: SHA-384

          • SHA-384是SHA-2家族中的一员,提供384位(48字节)的散列值

          • 基于SHA-512算法,使用不同的初始值和截断输出

          • 提供较高的安全性,适用于数字签名和消息认证

          • 在TLS1.3中用于:

            • 生成会话密钥

            • 验证握手消息的完整性

            • 数字签名

      • X.509 是密码学里公钥证书的格式标准,证书中主要包含以下信息:

        • 版本号:证书采用的X.509标准版本

        • 序列号:由CA分配的唯一标识符

        • 签名算法:用于签发证书的算法(如RSA、ECDSA等)

        • 颁发者信息:颁发证书的CA机构信息

          • 国家(C, Country)

          • 组织(O, Organization)

          • 组织单位(OU, Organization Unit)

          • 通用名称(CN, Common Name)

        • 有效期:证书的生效时间和过期时间

        • 主体信息:证书持有者的信息

          • 国家(C)

          • 省/州(ST, State)

          • 地区(L, Locality)

          • 组织(O)

          • 组织单位(OU)

          • 通用名称(CN)

        • 公钥信息:

          • 公钥算法

          • 公钥长度

          • 公钥值

        • 扩展信息:

          • 密钥用途

          • 主体备用名称(SAN)

          • CRL分发点

          • 基本约束

      • 服务端申请证书

        • 服务端管理员生成一对公钥和私钥,服务端将公钥和申请信息(域名,申请者信息)等发送给CA机构

        • CA机构核实服务端拥有着的信息,如组织是否存在、企业是否合法、是否拥有域名的所有权等

        • 核实无误后,CA机构使用自己的私钥对证书中的所有信息(版本号、序列号、签名算法、颁发者信息、有效期、主体信息、公钥信息、扩展信息等)进行签名

      • 客户端验证证书

        • 客户端在和服务端进行TLS握手时,服务端会将证书发送给客户端

        • 客户端首先检查证书的有效期、域名是否匹配等基本信息

        • 然后客户端会使用证书中的签名算法(在证书的签名算法字段中指定)和CA公钥来验证证书签名

        • 验证过程:

            1. 提取证书中除签名外的所有信息,使用相同的签名算法计算摘要

            1. 使用CA公钥验证证书中的签名,得到原始摘要

            1. 比较两个摘要是否一致,一致则说明证书确实是由该CA签发且未被篡改

          • RSA签名验证

            CA签名时:
             计算摘要: h = SHA256(证书信息)
             用私钥加密: signature = h^d mod n  # d是私钥指数,n是模数(两个大素数的乘积)
            
            验证签名时:
             用公钥解密: h' = signature^e mod n  # n是模数,与私钥中的n相同
             计算摘要: h = SHA256(证书信息)
             比较 h 和 h' 是否相等
            
            --------------------------------------------------------
            
            证书信息摘要: 123
            CA签名:
             私钥d = 3
             n = 33
             signature = 123^3 mod 33 = 9
            
            验证:
             公钥e = 7
             n = 33
             9^7 mod 33 = 123 (得到原始摘要)
            
            比对:
             计算当前证书信息的摘要是否等于123
        • 如果证书链中包含中间证书,则需要逐级验证直到根证书

            1. 首先验证服务器证书,使用中间证书的公钥验证服务器证书的签名

            1. 然后验证中间证书,使用根证书的公钥验证中间证书的签名

            1. 根证书是预先内置在系统/浏览器中的可信证书,不需要再验证

            1. 只有整个证书链都验证通过,才能确认服务器证书的可信性

        • 验证通过后,客户端才会信任该服务器证书,继续后续的TLS握手过程

      • 简单概括: 权威机构使用自己的私钥将主体信息加密成证书,客户端使用权威机构的公钥验证,通过则说明证书可信

      • 为什么需要中间证书?

        • 安全性:

          • 根证书是整个PKI体系的信任源,需要严格保护,通常离线存储

          • 使用中间证书可以保护根证书私钥,即使中间证书私钥泄露,根证书仍然安全

        • 灵活性:

          • 可以为不同业务场景颁发不同的中间证书

          • 中间证书出现问题时,可以单独吊销而不影响其他证书

        • 效率:

          • 根证书离线存储导致签发证书效率低

          • 中间证书可以在线运行,提高证书签发效率

        • 证书管理:

          • 可以通过中间证书将证书层级化管理

          • 便于证书的分类和权限控制

      • TLS 证书的文件后缀名并不重要,TLS 证书可以以纯文本形式存储(这是最常见的形式,适用于 Linux、Apache、Unix 和其他服务器),也可以以二进制形式存储(如 Java、Microsoft Server),证书以纯文本形式保存为 Base64 编码,二进制文件无法用文本编辑器打开

        • 常用编码

          • PEM

            • 这是最常用的证书存储格式。我们通常将 PEM 称为"文本格式",它是以 Base64 编码的。

            • PEM 是使用 ASCII 字母的 Base64 编码文件,PEM格式的文件使用Base64编码,并且通常以-----BEGIN ...-----和-----END ...-----包围起来,用来标识不同的部分。

          • DER

            • DER 格式是一种二进制证书格式。它不是文本,无法像文本一样打开阅读或复制。这是与 Base64 的主要区别。

            • 所有证书类型和私钥都可以存储为 DER 格式,DER 格式用于 Java 平台。

        • 常用后缀

          • CRT和CER 通常用于存储证书

          • KEY 通常用于存储私钥

          • PEM 可以仅包含证书、私钥或两者都有

        • 转换

          • 使用openssl可以将der编码的证书转换为pem编码的证书:

             openssl x509 -inform der -in cert.der -out cert.pem
          • 使用openssl可以将私钥(原始私钥格式)转换为pem编码的私钥:

             openssl rsa -in private.key -outform pem -out private.pem
          • 使用openssl可以将pem编码的证书和私钥组合在同一个pem文件中:

             cat cert.pem private.pem > combined.pem
      • OpenSSL是一个开放源代码的软件库,它提供了用于安全网络通信的加密和解密功能,包括和TLS协议的实现。由C语言编写,广泛用于各种操作系统上,如Linux、Unix以及类Unix系统。OpenSSL可以用来创建安全连接、生成证书、实现加密通信等,使用openssl命令行工具可以执行生成证书等操作,也可以借助一些开源工具,可以简化证书生成过程,如使用shell脚本构建的 https://github.com/acmesh-official/acme.sh

      • 使用openssl s_client -connect www.example.com:443 -showcerts 查看服务器证书

        # 连接到example.org服务器
        Connecting to 93.184.215.14
        CONNECTED(00000005)
        
        # 证书链验证过程
        # 验证根证书
        # 根证书信息: C(国家)=美国, O(组织)=DigiCert公司, OU(组织单位)=www.digicert.com, CN(通用名称)=DigiCert全球根证书G2
        depth=2 C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2
        # 验证通过,返回值为1表示验证成功
        verify return:1
        # 验证中间证书
        depth=1 C=US, O=DigiCert Inc, CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1  
        verify return:1
        # 验证服务器证书
        depth=0 C=US, ST=California, L=Los Angeles, O=Internet Corporation for Assigned Names and Numbers, CN=www.example.org
        verify return:1
        
        # 证书链详细信息
        ---
        Certificate chain
        # 服务器证书信息
        0 s:C=US, ST=California, L=Los Angeles, O=Internet Corporation for Assigned Names and Numbers, CN=www.example.org
        i:C=US, O=DigiCert Inc, CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1
        a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
        v:NotBefore: Jan 30 00:00:00 2024 GMT; NotAfter: Mar  1 23:59:59 2025 GMT
        
        # 服务器证书内容
        -----BEGIN CERTIFICATE-----
        MIIHbjCCBlagAwIBAgIQB1vO8waJyK3fE+Ua9K/hhzANBgkqhkiG9w0BAQsFADBZ
        [... 证书内容已省略 ...]
        -----END CERTIFICATE-----
        
        # 中间证书信息
        1 s:C=US, O=DigiCert Inc, CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1
        i:C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2
        a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
        v:NotBefore: Mar 30 00:00:00 2021 GMT; NotAfter: Mar 29 23:59:59 2031 GMT
        
        # 中间证书内容
        -----BEGIN CERTIFICATE-----
        MIIEyDCCA7CgAwIBAgIQDPW9BitWAvR6uFAsI8zwZjANBgkqhkiG9w0BAQsFADBh
        [... 证书内容已省略 ...]
        -----END CERTIFICATE-----
        
        # 服务器证书摘要
        ---
        Server certificate
        subject=C=US, ST=California, L=Los Angeles, O=Internet Corporation for Assigned Names and Numbers, CN=www.example.org
        issuer=C=US, O=DigiCert Inc, CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1
        
        # TLS连接信息:
        # - 未发送客户端证书CA名称列表
        # - 对等方使用的摘要算法: SHA256
        # - 对等方签名类型: RSA-PSS
        # - 服务器临时密钥: ECDH算法,使用prime256v1曲线,密钥长度256位
        ---
        No client certificate CA names sent
        Peer signing digest: SHA256
        Peer signature type: RSA-PSS
        Server Temp Key: ECDH, prime256v1, 256 bits
        
        # 握手统计
        ---
        SSL handshake has read 3821 bytes and written 765 bytes
        Verification: OK
        
        # TLS会话参数
        ---
        New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
        Protocol: TLSv1.3
        Server public key is 2048 bit
        This TLS version forbids renegotiation.
        Compression: NONE
        Expansion: NONE
        No ALPN negotiated
        Early data was not sent
        Verify return code: 0 (ok)
        
        # 会话票据信息
        ---
        Post-Handshake New Session Ticket arrived:
        SSL-Session:
        Protocol  : TLSv1.3
        Cipher    : TLS_AES_256_GCM_SHA384
        Session-ID: 9348876C0D58ABFB6EB4E6C4B80695A6F32EC23C689F4260E76DD018734F7F01
        [... 会话票据详细信息已省略 ...]
        
        # 连接关闭
        read R BLOCK
        closed
    •      Client                                     Server
           |                                         |
           |        1. ClientHello                   |
           |---------------------------------------->|
           |                                         |
           |        2. ServerHello                   |
           |        3. Certificate*                  |
           |        4. ServerKeyExchange*            |
           |        5. CertificateRequest*           |
           |        6. ServerHelloDone               |
           |<----------------------------------------|
           |                                         |
           |        7. Certificate*                  |
           |        8. ClientKeyExchange             |
           |        9. CertificateVerify*            |
           |        10.[ChangeCipherSpec]            |
           |        11.Finished                      |
           |---------------------------------------->|
           |                                         |
           |        12.[ChangeCipherSpec]            |
           |        13.Finished                      |
           |<----------------------------------------|
           |                                         |
           |        Application Encrypted Data       |
           |<--------------------------------------->|
      • []表示可选或者有条件的消息

      • *表示可以发送0个或多个该类型的消息

      • 流程解读

          1. ClientHello: 客户端向服务器发送客户端生成的随机数,可能的会话ID,支持的最高SSL版本,支持的加密套件列表,加密套件信息包括加密算法和密钥大小。

          1. ServerHello: 服务器选择客户端和服务器都支持的最高SSL版本(例如,如果客户端支持 TLS 1.1 版本,而服务器支持 1.2 版本,则应选择 1.1 版本;不应选择 1.2 版本。),最佳加密套件,以及服务端生成的随机数,可能的会话ID,并将此信息发送给客户端。

          1. Certificate(可选): 服务器向客户端发送证书或证书链。证书链通常以服务器的公钥证书开始,以证书颁发机构的根证书结束。此消息是可选的,根据选择的身份验证算法,可能需要证书。

          1. CertificateRequest(可选): 如果服务器必须验证客户端身份,则向客户端发送证书请求。在互联网应用中这种情况很少见。

          1. ServerKeyExchange(可选): 根据选择的密钥交换算法,服务器可能会向客户端发送服务器密钥交换消息。

          1. ServerHelloDone: 服务器告诉客户端已完成初始协商消息。

          1. Certificate(可选): 如果服务器请求客户端证书,客户端会发送其证书链,与服务器之前的操作类似。

          1. ClientKeyExchange: 客户端生成用于对称加密的密钥信息,对于RSA,客户端从服务器的 SSL 证书中获取公钥加密此密钥信息(预主密钥)并发送给服务器。对于DH系列的加密套件,此消息包含客户端的DH相关参数。

          1. CertificateVerify(可选): 当客户端提供证书时发送此消息。其目的是让服务器完成客户端身份验证过程。客户端使用加密哈希函数对信息进行数字签名,服务器用客户端公钥解密此信息来验证客户端身份。

          1. ChangeCipherSpec: 客户端发送消息告诉服务器切换到加密模式,后续数据传输使用协商的对称加密算法和密钥进行加密。

          1. Finished: 客户端告诉服务器已准备好开始安全数据通信。

          1. ChangeCipherSpec: 服务端发送消息告诉客户端切换到加密模式,后续数据传输使用协商的对称加密算法和密钥进行加密。

          1. Finished: 服务端告诉客户端已准备好开始安全数据通信。这标志着SSL握手的结束。

          1. 加密数据传输: 客户端和服务器使用在ClientHello和ServerHello期间协商的对称加密算法和加密哈希函数,以及客户端在ClientKeyExchange期间发送给服务器的密钥进行通信。此时可以重新协商握手。

        • 注意:

          • ClientHello 会发送会话 ID或ticket。但对于新连接,会话 ID或ticket 为空。只有在尝试恢复之前的会话时,才会发送非空的会话 ID或ticket。这是为了支持会话恢复(Session Resumption)机制

          • 在 RSA 握手中,预主密钥由客户端生成的随机数据组成。在 DH系列算法中,客户端和服务器使用商定的参数分别计算相同的预主密钥。

          • ServerKeyExchange和ClientKeyExchange不同算法的区别

            算法类型
            ServerKeyExchange
            ClientKeyExchange
            安全特性
            使用场景

            RSA

            不需要

            加密的预主密钥

            不提供前向安全性 实现简单 计算开销较大

            传统系统 简单部署场景

            DHE/ECDHE

            必需: DH/ECDH参数 临时公钥 参数签名

            客户端临时公钥

            完美前向安全性 每次会话新密钥 最高安全级别

            现代HTTPS 高安全需求场景

            DH/ECDH(静态)

            条件发送: 证书含参数则不需要 证书不含则需要

            客户端公钥

            有限前向安全性 密钥复用

            特定应用场景 性能优先场景

      • 实际握手举例

        • ClientHello请求细节

        • 向服务器发送了自己支持的加密套件

        • 支持的椭圆曲线

        • 支持的多种签名算法

          Frame 412: 373 bytes on wire (2984 bits), 373 bytes captured (2984 bits) on interface en0, id 0
          Ethernet II, Src: 26:67:51:4a:0e:17 (26:67:51:4a:0e:17), Dst: DongguanHuar_7c:22:fb (3c:c7:86:7c:22:fb)
          Internet Protocol Version 4, Src: 192.168.19.50, Dst: 153.3.238.110
          Transmission Control Protocol, Src Port: 52623, Dst Port: 443, Seq: 1, Ack: 1, Len: 319
          Transport Layer Security
              TLSv1.2 Record Layer: Handshake Protocol: Client Hello
                  Content Type: Handshake (22)
                  Version: TLS 1.2 (0x0303)
                  Length: 314
                  Handshake Protocol: Client Hello
                      Handshake Type: Client Hello (1)
                      Length: 310
                      Version: TLS 1.2 (0x0303)
                      Random: 080d07ab668fee92d5283979cfd677feb1458f13bd01c0d1a696eb12fba386c0
                          GMT Unix Time: Apr 13, 1974 15:54:19.000000000 CST
                          Random Bytes: 668fee92d5283979cfd677feb1458f13bd01c0d1a696eb12fba386c0
                      Session ID Length: 32
                      Session ID: 495c98be895dc023dba9cb5a8b6469a79bdc0d40ca160e5798bcd5784579943f
                      Cipher Suites Length: 98
                      Cipher Suites (49 suites)
                          Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303)
                          Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
                          /** 省略部分 **/
                          Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
                      Compression Methods Length: 1
                      Compression Methods (1 method)
                          Compression Method: null (0)
                      Extensions Length: 139
                      Extension: supported_versions (len=5) TLS 1.3, TLS 1.2
                          Type: supported_versions (43)
                          Length: 5
                          Supported Versions length: 4
                          Supported Version: TLS 1.3 (0x0304)
                          Supported Version: TLS 1.2 (0x0303)
                      Extension: key_share (len=38) x25519
                          Type: key_share (51)
                          Length: 38
                          Key Share extension
                              Client Key Share Length: 36
                              Key Share Entry: Group: x25519, Key Exchange length: 32
                                  Group: x25519 (29)
                                  Key Exchange Length: 32
                                  Key Exchange: 6be2999b6a58d7a19f9c4464f2d482201d4a1bc6bd7bc17a09b5bc9bf804ec48
                      Extension: server_name (len=18) name=www.baidu.com
                          Type: server_name (0)
                          Length: 18
                          Server Name Indication extension
                              Server Name list length: 16
                              Server Name Type: host_name (0)
                              Server Name length: 13
                              Server Name: www.baidu.com
                      Extension: ec_point_formats (len=2)
                          Type: ec_point_formats (11)
                          Length: 2
                          EC point formats Length: 1
                          Elliptic curves point formats (1)
                              EC point format: uncompressed (0)
                      Extension: supported_groups (len=10)
                          Type: supported_groups (10)
                          Length: 10
                          Supported Groups List Length: 8
                          Supported Groups (4 groups)
                              Supported Group: x25519 (0x001d)
                              Supported Group: secp256r1 (0x0017)
                              Supported Group: secp384r1 (0x0018)
                              Supported Group: secp521r1 (0x0019)
                      Extension: signature_algorithms (len=24)
                          Type: signature_algorithms (13)
                          Length: 24
                          Signature Hash Algorithms Length: 22
                          Signature Hash Algorithms (11 algorithms)
                              Signature Algorithm: rsa_pss_rsae_sha512 (0x0806)
                                  Signature Hash Algorithm Hash: Unknown (8)
                                  Signature Hash Algorithm Signature: Unknown (6)
                               /** 省略部分 **/
                                  Signature Hash Algorithm Hash: SHA1 (2)
                                  Signature Hash Algorithm Signature: ECDSA (3)
                      Extension: application_layer_protocol_negotiation (len=14)
                          Type: application_layer_protocol_negotiation (16)
                          Length: 14
                          ALPN Extension Length: 12
                          ALPN Protocol
                              ALPN string length: 2
                              ALPN Next Protocol: h2
                              ALPN string length: 8
                              ALPN Next Protocol: http/1.1
                      [JA4: t13d4907h2_0d8feac7bc37_7395dae3b2f3]
                      [JA4_r [truncated]: t13d4907h2_0004,0005,000a,0016,002f,0033,0035,0039,003c,003d,0041,0045,0067,006b,0081,0084,0088,009c,009d,009e,009f,00ba,00be,00c0,00c4,00ff,1301,1302,1303,c007,c008,c009,c00a,c011,c012,c013,c014,c023,c024,c027,c028,c02b]
                      [JA3 Fullstring [truncated]: 771,4867-4866-4865-52393-52392-52394-49200-49196-49192-49188-49172-49162-159-107-57-65413-196-136-129-157-61-53-192-132-49199-49195-49191-49187-49171-49161-158-103-51-190-69-156-60-47-186-65-49169-49159-5-4-4917]
                      [JA3: 375c6162a492dfbf2795909110ce8424]
          
        • ServerHello请求细节

        • 服务器选用的加密套件为TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

          • 使用 ECDHE 进行密钥交换

            • 因为使用ECDHE进行密钥交换,在tls1.2中会有专门的ServerKeyExchange 和 ClientKeyExchange阶段

          • RSA 用于认证

          • AES-128-GCM 用于加密

          • SHA256 用于哈希

          Frame 416: 1334 bytes on wire (10672 bits), 1334 bytes captured (10672 bits) on interface en0, id 0
          Ethernet II, Src: DongguanHuar_7c:22:fb (3c:c7:86:7c:22:fb), Dst: 26:67:51:4a:0e:17 (26:67:51:4a:0e:17)
          Internet Protocol Version 4, Src: 153.3.238.110, Dst: 192.168.19.50
          Transmission Control Protocol, Src Port: 443, Dst Port: 52623, Seq: 1, Ack: 320, Len: 1280
          Transport Layer Security
              TLSv1.2 Record Layer: Handshake Protocol: Server Hello
                  Content Type: Handshake (22)
                  Version: TLS 1.2 (0x0303)
                  Length: 102
                  Handshake Protocol: Server Hello
                      Handshake Type: Server Hello (2)
                      Length: 98
                      Version: TLS 1.2 (0x0303)
                      Random: 67738e87efe82702b2befa953b7447d0378458bfcedc3b50f3167ab4d29b8196
                          GMT Unix Time: Dec 31, 2024 14:26:15.000000000 CST
                          Random Bytes: efe82702b2befa953b7447d0378458bfcedc3b50f3167ab4d29b8196
                      Session ID Length: 32
                      Session ID: 754d94678cd10b5f302a8909fa3faf0619f3ee1a4cd9b6ea5a6c468ec2204558
                      Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
                      Compression Method: null (0)
                      Extensions Length: 26
                      Extension: renegotiation_info (len=1)
                          Type: renegotiation_info (65281)
                          Length: 1
                          Renegotiation Info extension
                              Renegotiation info extension length: 0
                      Extension: application_layer_protocol_negotiation (len=11)
                          Type: application_layer_protocol_negotiation (16)
                          Length: 11
                          ALPN Extension Length: 9
                          ALPN Protocol
                              ALPN string length: 8
                              ALPN Next Protocol: http/1.1
                      Extension: ec_point_formats (len=2)
                          Type: ec_point_formats (11)
                          Length: 2
                          EC point formats Length: 1
                          Elliptic curves point formats (1)
                              EC point format: uncompressed (0)
                      [JA3S Fullstring: 771,49199,65281-16-11]
                      [JA3S: 2de81c22ea32a57162df5cb08d4a2795]
              TLS segment data (1173 bytes)
          
    •        Client                                           Server
      
            Key  ^ ClientHello
            Exch | + key_share*
                 | + signature_algorithms*
                 | + psk_key_exchange_modes*
                 v + pre_shared_key*       -------->
                                                              ServerHello  ^ Key
                                                             + key_share*  | Exch
                                                        + pre_shared_key*  v
                                                    {EncryptedExtensions}  ^  Server
                                                    {CertificateRequest*}  v  Params
                                                           {Certificate*}  ^
                                                     {CertificateVerify*}  | Auth
                                                               {Finished}  v
                                           <--------  [Application Data*]
                 ^ {Certificate*}
            Auth | {CertificateVerify*}
                 v {Finished}              -------->
                   [Application Data]      <------->  [Application Data]
      
            +  表示在前面提到的消息中发送的重要扩展。
            *  表示可选的或依情况而定的消息/扩展,不是总是会发送。
            {} 表示使用从[发送方]_handshake_traffic_secret派生的密钥保护的消息。
            [] 表示使用从[发送方]_application_traffic_secret_N派生的密钥保护的消息。
      • 流程解读:

          1. ClientHello: 客户端发送支持的加密套件列表、key_share扩展(包含客户端的ECDH公钥)等信息

          1. ServerHello: 服务器选择加密套件,并在key_share扩展中发送自己的ECDH公钥,如果服务端不支持客户端的加密算法,则发送HelloRetryRequest通知

          2. 在TLS 1.3中,keyShare是客户端和服务器在密钥交换过程中发送的临时公钥(通常是椭圆曲线公钥或Diffie-Hellman公钥)。这个公钥用于生成共享密钥(Pre-Master Secret),但它本身并不使用私钥进行签名。这是因为keyShare的目的是为了密钥交换,而不是身份验证。身份验证是通过其他机制(如certificateVerify)来完成的。

          1. EncryptedExtensions(可选): 服务器发送加密的扩展数据

          1. CertificateRequest(可选): 如果需要客户端认证,服务器发送证书请求

          1. Certificate(可选): 服务器发送证书链

          1. CertificateVerify(可选): 服务器使用私钥对之前的握手消息进行签名

          2. CertificateVerify消息的作用是证明发送方持有证书中公钥对应的私钥,具体实现如下:

              1. 握手消息哈希计算

              2. 记录从ClientHello到CertificateVerify之前的所有握手消息

              3. 计算这些消息的哈希值(通常使用SHA-256等),称为握手上下文哈希

              1. 签名内容构造

              2. 签名内容格式为: "TLS 1.3, certificate verify" + 0x00 + 握手上下文哈希

              3. 固定字符串用于区分签名用途

              1. 私钥签名

              2. 使用私钥对构造的内容进行签名(RSA-PSS/ECDSA等)

              3. 将签名放入CertificateVerify消息中发送

              1. 接收方验证

              2. 重新计算握手消息哈希值

              3. 使用发送方证书公钥验证签名

              4. 验证签名内容是否匹配预期格式

              1. 安全保证

              2. 只有持有私钥才能生成有效签名

              3. 签名包含所有握手消息哈希,防止篡改

              4. 确保了不可抵赖性和完整性

          1. Finished: 服务器发送验证数据,确认握手完成

          2. Finished消息的作用和实现

            • 作用:验证握手过程的完整性,确保消息未被篡改

            • 基于HMAC(Hash-based Message Authentication Code)实现

            • HMAC的输入包括:

              • 握手上下文哈希:从ClientHello到Finished之前所有消息的哈希值

              • 固定字符串:

                • 客户端使用"client finished"

                • 服务器使用"server finished"

            • HMAC密钥:

              • 从主密钥(Master Secret)通过HKDF派生

              • 分别生成客户端和服务器的finished密钥

            • HMAC计算:

              HMAC_Value = HMAC(
                  finished_key,
                  "client finished" + Handshake Context Hash  // 客户端
                  OR
                  "server finished" + Handshake Context Hash  // 服务器
              )
            • 验证流程:

                1. 接收方重新计算握手消息哈希值

                1. 使用finished密钥验证HMAC

                1. 比较计算值与接收值是否一致

                1. 不一致则终止连接

            • 安全保证:

              • 只有持有正确密钥才能生成/验证HMAC

              • 任何消息篡改都会导致验证失败

              • 有效防止中间人攻击

          1. Certificate(可选): 如果服务器请求了客户端证书,客户端发送证书

          1. CertificateVerify(可选): 如果发送了客户端证书,客户端对握手消息签名

          1. Finished: 客户端发送验证数据,确认握手完成

        • 上图使用wireshark对curl https://www.example.com 握手过程进行抓包

      • 实际握手举例:

        • 上图使用wireshark对curl https://www.example.com 握手过程进行抓包

        • 服务器返回Hello Retry Request 的原因是服务端未接受客户端第一次发送的加密算法,对比两次Client Hello 请求

          # 第一次
          Extension: key_share (len=38) x25519
            Type: key_share (51)
            Length: 38
            Key Share extension
            Client Key Share Length: 36
            Key Share Entry: Group: x25519, Key Exchange length: 32
            Group: x25519 (29)
            Key Exchange Length: 32
            Key Exchange: 6fc363b9fc781bc9fec7b366a3fe99e88025fe87d16bc1acefee7098458c3101
            
          # HelloRetry Request  
            Extension: key_share (len=2) secp256r1
            Type: key_share (51)
            Length: 2
            Key Share extension
            Selected Group: secp256r1 (23)
          
          # 第二次
          Extension: key_share (len=71) secp256r1
            Type: key_share (51)
            Length: 71
            Key Share extension
            Client Key Share Length: 69
            Key Share Entry: Group: secp256r1, Key Exchange length: 65
            Group: secp256r1 (23)
            Key Exchange Length: 65
            Key Exchange: 040f6a84376a715cf75e734e20b21062f72edd9034ac3d82456db978542d41a10f2e1fb991fdf2f293a6c450c5f3531e6fc4467422c6f4d68b48e685a1ae10322f	
        • 第二次ClientHello请求细节

          • 向服务器发送了自己支持的加密套件

              1. TLS_AES_256_GCM_SHA384

              2. TLS_CHACHA20_POLY1305_SHA256

              3. TLS_AES_128_GCM_SHA256

          • 支持的椭圆曲线

          • 支持的多种签名算法

          • Extension: key_share中设置使用secp256r1椭圆曲线进行密钥交换,并且发送自己的ECDH公钥值

            Frame 26024: 354 bytes on wire (2832 bits), 354 bytes captured (2832 bits) on interface en0, id 0
            Ethernet II, Src: 26:67:51:4a:0e:17 (26:67:51:4a:0e:17), Dst: DongguanHuar_7c:22:fb (3c:c7:86:7c:22:fb)
            Internet Protocol Version 4, Src: 192.168.19.50, Dst: 93.184.215.14
            Transmission Control Protocol, Src Port: 60820, Dst Port: 443, Seq: 250, Ack: 100, Len: 288
            Transport Layer Security
                TLSv1.3 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
                    Content Type: Change Cipher Spec (20)
                    Version: TLS 1.2 (0x0303)
                    Length: 1
                    Change Cipher Spec Message
                TLSv1.3 Record Layer: Handshake Protocol: Client Hello
                    Content Type: Handshake (22)
                    Version: TLS 1.2 (0x0303)
                    Length: 277
                    Handshake Protocol: Client Hello
                        Handshake Type: Client Hello (1)
                        Length: 273
                        Version: TLS 1.2 (0x0303)
                        Random: 9a9b927033f057ee12c42a3641d96cfbff2d7ca419a52e1786e3d0d21a2cbba0
                        Session ID Length: 32
                        Session ID: 8b6f8d83cd756d328a9cc6ae04909084a424d15c5635ac23cc6f65d3e2cba63e
                        Cipher Suites Length: 6
                        Cipher Suites (3 suites)
                            Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
                            Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303)
                            Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
                        Compression Methods Length: 1
                        Compression Methods (1 method)
                            Compression Method: null (0)
                        Extensions Length: 194
                        Extension: server_name (len=16) name=example.com
                            Type: server_name (0)
                            Length: 16
                            Server Name Indication extension
                                Server Name list length: 14
                                Server Name Type: host_name (0)
                                Server Name length: 11
                                Server Name: example.com
                        Extension: ec_point_formats (len=4)
                            Type: ec_point_formats (11)
                            Length: 4
                            EC point formats Length: 3
                            Elliptic curves point formats (3)
                                EC point format: uncompressed (0)
                                EC point format: ansiX962_compressed_prime (1)
                                EC point format: ansiX962_compressed_char2 (2)
                        Extension: supported_groups (len=22)
                            Type: supported_groups (10)
                            Length: 22
                            Supported Groups List Length: 20
                            Supported Groups (10 groups)
                                Supported Group: x25519 (0x001d)
                                Supported Group: secp256r1 (0x0017)
                                Supported Group: x448 (0x001e)
                                Supported Group: secp521r1 (0x0019)
                                Supported Group: secp384r1 (0x0018)
                         		/*省略部分*/
                        Extension: session_ticket (len=0)
                            Type: session_ticket (35)
                            Length: 0
                            Session Ticket: <MISSING>
                        Extension: encrypt_then_mac (len=0)
                            Type: encrypt_then_mac (22)
                            Length: 0
                        Extension: extended_master_secret (len=0)
                            Type: extended_master_secret (23)
                            Length: 0
                        Extension: signature_algorithms (len=36)
                            Type: signature_algorithms (13)
                            Length: 36
                            Signature Hash Algorithms Length: 34
                            Signature Hash Algorithms (17 algorithms)
                                Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
                                    Signature Hash Algorithm Hash: SHA256 (4)
                                    Signature Hash Algorithm Signature: ECDSA (3)
                       			/**省略部分 **/
                                Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
                                    Signature Hash Algorithm Hash: SHA512 (6)
                                    Signature Hash Algorithm Signature: RSA (1)
                        Extension: supported_versions (len=3) TLS 1.3
                            Type: supported_versions (43)
                            Length: 3
                            Supported Versions length: 2
                            Supported Version: TLS 1.3 (0x0304)
                        Extension: psk_key_exchange_modes (len=2)
                            Type: psk_key_exchange_modes (45)
                            Length: 2
                            PSK Key Exchange Modes Length: 1
                            PSK Key Exchange Mode: PSK with (EC)DHE key establishment (psk_dhe_ke) (1)
                        Extension: key_share (len=71) secp256r1
                            Type: key_share (51)
                            Length: 71
                            Key Share extension
                                Client Key Share Length: 69
                                Key Share Entry: Group: secp256r1, Key Exchange length: 65
                                    Group: secp256r1 (23)
                                    Key Exchange Length: 65
                                    Key Exchange: 040f6a84376a715cf75e734e20b21062f72edd9034ac3d82456db978542d41a10f2e1fb991fdf2f293a6c450c5f3531e6fc4467422c6f4d68b48e685a1ae10322f
                        [JA4: t13d031000_55b375c5d22e_3eb3b556ea2c]
                        [JA4_r: t13d031000_1301,1302,1303_000a,000b,000d,0016,0017,0023,002b,002d,0033_0403,0503,0603,0807,0808,081a,081b,081c,0809,080a,080b,0804,0805,0806,0401,0501,0601]
                        [JA3 Fullstring: 771,4866-4867-4865,0-11-10-35-22-23-13-43-45-51,29-23-30-25-24-256-257-258-259-260,0-1-2]
                        [JA3: c3eddff4f56c6811c9b3be93e9b13273]
            
        • ServerHello请求细节

          • 使用的加密套件为TLS_AES_256_GCM_SHA384

          • Extension: key_share中设置使用secp256r1椭圆曲线进行密钥交换,并且发送自己的ECDH公钥值

            Transport Layer Security
                TLSv1.3 Record Layer: Handshake Protocol: Server Hello
                    Content Type: Handshake (22)
                    Version: TLS 1.2 (0x0303)
                    Length: 155
                    Handshake Protocol: Server Hello
                        Handshake Type: Server Hello (2)
                        Length: 151
                        Version: TLS 1.2 (0x0303)
                        Random: 8e38c96f0707cd108a8f0b39fb72f3cd64287a22ee95f13ec5de8642195914b7
                        Session ID Length: 32
                        Session ID: 3015c3341bcadcc0f9010249980594d3674d086b11f333cd8d001da5156bf2a0
                        Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
                        Compression Method: null (0)
                        Extensions Length: 79
                        Extension: supported_versions (len=2) TLS 1.3
                            Type: supported_versions (43)
                            Length: 2
                            Supported Version: TLS 1.3 (0x0304)
                        Extension: key_share (len=69) secp256r1
                            Type: key_share (51)
                            Length: 69
                            Key Share extension
                                Key Share Entry: Group: secp256r1, Key Exchange length: 65
                                    Group: secp256r1 (23)
                                    Key Exchange Length: 65
                                    Key Exchange: 0491cc138fd8dc8b88f247177607a1be67b32be79ea55fe2ebeaa731bd6adcba980edef70c56ba0ea85161dccd28d853a6f5b31035a74b8bec6d9f3feeefe94faa
                        [JA3S Fullstring: 771,4866,43-51]
                        [JA3S: 15af977ce25de452b96affa2addb1036]
                TLSv1.3 Record Layer: Application Data Protocol: Hypertext Transfer Protocol
                    Opaque Type: Application Data (23)
                    Version: TLS 1.2 (0x0303)
                    Length: 32
                    Encrypted Application Data: 2839ea62c00bb9cf01c106d1e8ae90f8d016b630d75e1e78d37145e0dc2f4bc7
                    [Application Data Protocol: Hypertext Transfer Protocol]
                TLS segment data (1071 bytes)
            
      • 减少握手开销:完整的 TLS 握手需要多次往返和复杂的加密运算

      • 提高性能:重用之前协商的密钥材料,加快连接建立速度

      • 降低服务器负载:减少CPU密集型的加密操作

      • Session ID(TLS1.2):

        • 在首次完整 TLS 握手时,服务器生成一个唯一的 Session ID 并与会话相关的密钥材料(如主密钥、加密套件等)一起存储在服务器端;当客户端再次连接时,通过在 ClientHello 消息中携带之前获得的 Session ID,服务器检查并找到对应的会话信息后,双方就可以直接重用之前协商的密钥材料,从而跳过证书验证和密k钥交换等步骤,大大减少了握手往返次数和计算开销。

      • Session Ticket(TLS1.2):

        • 服务器不再存储会话状态,而是在首次握手完成时,将会话信息(包括主密钥、加密套件等)用票据加密密钥(Ticket Encryption Key)加密后,以票据(Ticket)的形式发送给客户端保存;当客户端再次连接时,将保存的票据在 ClientHello 中发回服务器,服务器使用相同的票据加密密钥解密该票据以恢复会话状态,从而实现无状态的会话复用,这种机制特别适合需要横向扩展的大规模部署场景

      • PSK(TLS1.3):

        • 在 TLS 1.3 中,ID和Ticket的方式已经被弃用,使用PSK方式

        • PSK(Pre-Shared Key)会话恢复机制的工作原理是:当首次完整 TLS 握手完成时,服务器会生成一个包含会话参数的加密票据(ticket)发送给客户端保存,在后续连接中,客户端可以在 ClientHello 消息中携带这个 PSK 标识符,如果服务器验证有效,双方就可以使用这个预共享密钥(配合新的 (EC)DHE 密钥交换)快速建立安全连接,从而避免了完整的握手过程,同时保证了前向安全性。

        • 优点:

          • 安全性更高,强制与 (EC)DHE 结合使用,提供完美前向保密(PFS)

          • 握手过程更简化,支持 0-RTT 数据传输

          • 扩展性更好,无需跨服务器同步状态,适合分布式系统部署,更容易实现负载均衡

      • TLS1.2如何确定使用的哪种方式

        • 在TLS1.2中 通过观察 TLS 握手过程中的数据包特征可以确定使用的复用机制:如果看到 ClientHello 中包含非空的 Session ID 且 ServerHello 返回相同的 Session ID 进行复用,则是使用 Session ID 机制;如果看到 ClientHello 中包含 session_ticket 扩展并携带之前的票据,且在握手过程中出现 NewSessionTicket 消息,则是使用 Session Ticket 机制;此外,虽然客户端可能同时支持两种机制,但最终使用哪种取决于服务器的选择和响应。

    •       Client                                                Server
      
            ClientHello                   -------->
                                                             ServerHello
                                                      [ChangeCipherSpec]
                                          <--------             Finished
            [ChangeCipherSpec]
            Finished                      -------->
            Application Data              <------->     Application Data
      
      
        1. 客户端发送 ClientHello 消息,包含要恢复的会话的 Session ID

        1. 服务器检查其会话缓存是否存在匹配的 Session ID

        2. 如果找到匹配且服务器愿意重用该会话:

          • 服务器发送 ServerHello,使用相同的 Session ID

          • 双方直接发送 ChangeCipherSpec 消息

          • 双方交换 Finished 消息

          • 握手完成后可以开始交换应用层数据

        3. 如果未找到匹配:

          • 服务器生成新的 Session ID

          • 执行完整的 TLS 握手流程

    • 1 RTT

            ClientHello
                + key_share*
                + pre_shared_key          -------->
                                                                ServerHello
                                                           + pre_shared_key
                                                               + key_share*
                                                      {EncryptedExtensions}
                                                                 {Finished}
                                          <--------     [Application Data*]
                {Finished}                -------->
                [Application Data]        <------->      [Application Data
                
      			  +  表示在前面提到的消息中发送的重要扩展。
                    *  表示可选的或依情况而定的消息/扩展,不是总是会发送。
                    {} 表示使用从[发送方]_handshake_traffic_secret派生的密钥保护的消息。
                    [] 表示使用从[发送方]_application_traffic_secret_N派生的密钥保护的消息。
      
        1. 客户端发送 ClientHello 消息,包含:

        2. pre_shared_key 扩展,包含之前获得的 PSK 标识符

        3. key_share 扩展,用于 (EC)DHE 密钥交换

        1. 服务器响应:

        2. 验证 PSK 有效性

        3. 发送 ServerHello,包含选中的 PSK 和 key_share

        4. 发送 EncryptedExtensions

        5. 发送 Finished 消息

        1. 客户端发送 Finished 消息

        1. 握手完成,双方可以开始交换加密的应用数据

    • 0 RTT

               Client                                               Server
      
               ClientHello
               + early_data
               + key_share*
               + psk_key_exchange_modes
               + pre_shared_key
               (Application Data*)     -------->
                                                               ServerHello
                                                          + pre_shared_key
                                                              + key_share*
                                                     {EncryptedExtensions}
                                                             + early_data*
                                                                {Finished}
                                       <--------       [Application Data*]
               (EndOfEarlyData)
               {Finished}              -------->
               [Application Data]      <------->        [Application Data]
      
            + 表示在之前提到的消息中发送的值得注意的扩展
            * 表示可选的或情况相关的消息/扩展,不是每次都会发送
            () 表示使用从 client_early_traffic_secret 派生的密钥保护的消息
            {} 表示使用从 [发送方]_handshake_traffic_secret 派生的密钥保护的消息
            [] 表示使用从 [发送方]_application_traffic_secret_N 派生的密钥保护的消息
        1. 客户端发送 ClientHello 消息,包含:

        2. early_data 扩展,表明要发送 0-RTT 数据

          • early_data代表在TLS握手完成之前发送的数据

        3. key_share 扩展,用于密钥交换

        4. pre_shared_key 扩展,包含之前会话的 PSK

        5. psk_key_exchange_modes 扩展,指定 PSK 密钥交换模式

        6. 可以立即发送加密的应用数据(0-RTT 数据)

        1. 服务器响应:

        2. 验证 PSK 有效性

        3. 发送 ServerHello,包含:

          • pre_shared_key 扩展,确认使用的 PSK

          • key_share 扩展,用于密钥交换

        4. 发送 EncryptedExtensions,包含:

          • early_data 扩展,表明接受 0-RTT 数据

        5. 发送 Finished 消息

        6. 可以开始发送加密的应用数据

        1. 客户端:

        2. 发送 EndOfEarlyData 消息,表明 0-RTT 数据发送完成

        3. 发送 Finished 消息

        1. 握手完成,双方可以继续交换加密的应用数据

      • 注意事项:

        • 0-RTT 数据可能被重放,需要应用层防重放机制

        • 服务器可以拒绝 0-RTT 数据,此时需要完整 1-RTT 握手

        • 0-RTT 仅支持部分加密套件和应用数据

最后更新于