TLS协议讲解(二)

发布时间:2026/7/16 8:47:29

TLS协议讲解(二) SSL (Secure Sockets Layer安全套接层。。主要任务是提供私密性信息完整性和身份认证。证书和握手签名 - 身份认证 AES-GCM 加密 - 数据机密性 GCM 认证标签 - 传输数据完整性 Finished - TLS 握手完整性一、SSL/TLS记录协议层记录协议是整个 SSL/TLS 的核心数据封装层。它主要完成对上层数据进行分段添加完整性校验或认证标签对数据加密添加记录头交给 TCP 发送在 TLS 1.2 中一个记录头通常是 5 字节------------------------------------- | Content Type | TLS Version | Length | | 1字节 | 2字节 | 2字节 | ------------------------------------- | 加密后的内容 | -----------------------------------------Content Type用于说明当前记录装的是什么20ChangeCipherSpec 21Alert 22Handshake 23Application Data因此接收方解密一个 TLS 记录后就能根据类型字段知道应该把内容交给谁处理。TLS 1.2 的记录协议会把上层数据分片每个明文片段最大通常为2^14 16384字节。RFC 编辑器二、SSL/TLS握手协议层握手协议不负责传输普通业务数据它负责在正式通信前建立安全连接。主要任务包括协商 TLS 版本协商密码套件交换随机数进行密钥交换服务器发送证书证明服务器身份可选地验证客户端身份双方计算出相同的会话密钥使用Finished消息验证握手过程没有被篡改TLS 1.2 的简化握手过程可以理解为客户端 服务器 ClientHello ---------------- ---------------- ServerHello Certificate ServerKeyExchange ServerHelloDone ClientKeyExchange ---------------- ChangeCipherSpec ---------------- Finished ---------------- ---------------- ChangeCipherSpec ---------------- Finished实际消息会因为密码套件、客户端证书、会话恢复等情况而变化。握手协议产生的消息例如ClientHello、Certificate、Finished最终也要交给记录协议封装ClientHello ↓ Handshake消息头 ↓ TLS记录协议封装 ↓ TCP发送所以网络抓包里看到的是TLS Record Content Type Handshake 里面包含 ClientHello握手的最终结果是生成供记录协议使用的密钥和安全参数。RFC 编辑器三、SSL密码参数修改协议层它的英文是Change Cipher Spec Protocol这个名字容易让人误解。它不是用来重新协商具体加密算法的。真正的算法协商是在握手协议的ClientHello和ServerHello中完成的。在 TLS 1.2 中通信双方内部会暂时维护两套状态当前状态 current state 待启用状态 pending state握手协商期间新产生的加密算法MAC算法加密密钥IV等参数先放在pending state中。当一方发送ChangeCipherSpec后意思是从接下来的记录开始启用刚刚协商好的加密参数。TLS 1.2 的ChangeCipherSpec消息本身很简单内容只有一个字节01其作用不是携带密钥而是发送一个“切换状态”的信号。RFC 编辑器可以理解成握手协议 我们已经协商好使用哪把锁、哪把钥匙。 ChangeCipherSpec 从下一条消息开始正式使用这把锁和钥匙。需要注意TLS 1.3 已经不再依靠 ChangeCipherSpec 来切换密码状态。TLS 1.3 中它主要为了兼容某些旧网络设备而保留接收方通常忽略它不应把它理解成 TLS 1.3 的真正密钥切换机制。TLS 1.3 的密钥状态切换由握手流程本身决定。RFC 编辑器四、SSL告警协议层告警协议用于报告错误异常安全问题正常关闭连接常见告警包括close_notify unexpected_message bad_record_mac handshake_failure bad_certificate certificate_expired illegal_parameter例如接收方解密后发现认证标签不正确可能发送bad_record_mac如果服务器证书验证失败可能产生证书相关告警。如果通信双方需要正常关闭 TLS 连接会发送close_notify它表示我的 TLS 数据已经发送完了不会再发送新的应用数据。告警消息同样不是直接交给 TCP而是经过记录协议Alert消息 ↓ TLS记录协议加密封装 ↓ TCP发送早期 TLS 中告警分为warning和fatal发生致命告警时连接应立即终止。SSL 记录协议、握手协议、密码参数修改协议、告警协议不是四个依次经过的层。正确结构是握手协议 Handshake / 告警协议 Alert / 密码参数修改协议 ChangeCipherSpec / 应用数据 Application Data │ ▼ SSL/TLS 记录协议 │ ▼ TCP │ ▼ IP/以太网也就是说记录协议是底层承载层握手、告警、密码参数修改和应用数据都是它承载的不同类型的数据。握手、告警和 ChangeCipherSpec 只在需要的时候产生自己的消息再分别交给记录协议。五、记录协议具体怎样修改应用消息以 TLS 1.2 为例假设应用层提交了 30000 字节数据。第一步分段TLS 可能把它拆成第1个TLS明文片段16384字节 第2个TLS明文片段13616字节注意TLS记录边界和应用层消息边界不一定一致。一条应用消息可能拆成多个 TLS 记录多个较小的应用写入也可能被实现合并处理。第二步压缩旧版 TLS 结构中存在压缩步骤TLSPlaintext ↓ TLSCompressed但实际现代 TLS 通信中通常不使用 TLS 压缩压缩方法一般是null也就是不压缩。第三步完整性保护和加密具体过程取决于使用的密码套件。传统 CBC 类密码套件大致过程是明文 ↓ 计算MAC并附加 ↓ 添加填充Padding ↓ 加密形成类似[应用数据][MAC][Padding][Padding Length] ↓ 加密AEAD密码套件例如 AES-GCM、ChaCha20-Poly1305大致是明文 附加认证数据 ↓ AEAD加密 ↓ 密文 Authentication TagAEAD 同时提供机密性别人看不懂完整性别人不能偷偷修改身份认证确认数据由持有密钥的一方生成TLS 1.3 只允许使用现代 AEAD 类密码套件。RFC 编辑器第四步添加记录头形成 TLS 记录----------------------------- | Content Type | ----------------------------- | Version | ----------------------------- | Length | ----------------------------- | Encrypted Application Data | -----------------------------对于普通业务数据TLS 1.2 中Content Type 23表示Application Data。第五步交给TCPTLS 把记录作为一串字节交给 TCPTLS Record 1 TLS Record 2TCP 不知道里面是HTTPTLS握手TLS告警应用数据TCP只看到字节流。TCP可能把一个 TLS 记录拆成多个 TCP 段一个TLS Record ↓ TCP段1 TCP段2 TCP段3也可能一次 TCP 接收缓冲区中包含多个 TLS 记录的一部分或全部。因此接收方不能认为一次 recv() 一个 TLS RecordTLS实现必须根据记录头中的Length字段不断缓存和解析。六、接收端执行相反过程接收端的大致过程从TCP读取字节流 ↓ 读取5字节TLS记录头 ↓ 根据Length读取完整记录 ↓ 解密 ↓ 验证MAC或AEAD认证标签 ↓ 得到明文内容 ↓ 根据Content Type分发分发过程Content Type 22 → 交给握手协议 Content Type 21 → 交给告警协议 Content Type 20 → 处理ChangeCipherSpec Content Type 23 → 交给HTTP等应用层如果解密或完整性验证失败则不能把数据交给应用层通常会终止连接。七、完整阶段图建立连接阶段应用程序 │ │ 请求建立TLS连接 ▼ 握手协议 │ ├─ 协商版本和算法 ├─ 验证证书 ├─ 交换密钥 └─ 生成会话密钥 │ ▼ ChangeCipherSpec主要针对TLS 1.2 │ ▼ Finished验证 │ ▼ TLS安全连接建立这些消息全部由记录协议封装并通过 TCP 发送。业务数据阶段HTTP/其他应用消息 ↓ TLS记录协议 ├─ 分段 ├─ 完整性保护 ├─ 加密 └─ 添加记录头 ↓ TCP ↓ IP ↓ 以太网出错或关闭阶段检测到错误或准备关闭 ↓ Alert协议生成告警消息 ↓ TLS记录协议封装 ↓ TCP发送最核心的关系可以记成一句话握手协议负责建立密钥和安全参数ChangeCipherSpec负责在旧版TLS中通知启用参数告警协议负责报告状态和错误记录协议负责把它们以及应用数据统一封装、保护并发送。八、SSL建立阶段可以分为两个大阶段1SSL建立的第一阶段Handshake phase握手阶段协商加密算法认证服务器建立用于加密和MACMessage Authentication Code用的密钥该阶段类似于IPSec VPN IKE的作用。2SSL建立第二阶段Secure data transfer phase安全的数据传输阶段在已经建立的SSL连接里安全的传输数据。该阶段类似于IPSec VPN ESP的作用SSL原理SSL建立握手协议总过程图SSL建立总过程在用SSL进行通信之前首先要使用SSL的Handshake协议在通信两端握手协商数据传输中要用到的相关安全参数如加密算法、共享密钥、产生密钥所要的材料等并对对端的身份进行验证。SSL的建立过程总共有13个包第一次建立至少需要9个包。SSL建立第一阶段客户端首先发送ClientHello消息到服务端服务端收到ClientHello消息后再发送ServerHello消息回应客户端。图SSL建立第一阶段报文交换示意图ClientHello握手第一步是客户端向服务端发送 Client Hello 消息这个消息里包含了一个客户端生成的随机数Random1、客户端支持的加密套件Support Ciphers和 SSL Version 等信息。图ClinetHello报文抓包示例ClientHello中涉及到的消息具体如下客户端版本按优先级列出客户端支持的协议版本首选客户端希望支持的最新协议版本。客户端随机数Random会话IDSession id如果客户端第一次连接到服务器那么这个字段就会保持为空。上图中该字段为空说明这是第一次连接到服务器。如果该字段不为空说明以前是与服务器有连接的在此期间服务器将使用Session ID映射对称密钥并将Session ID存储在客户端浏览器中为映射设置一个时间限。如果浏览器将来连接到同一台服务器在时间到期之前它将发送Session ID服务器将对映射的Session ID进行验证并使用以前用过的对称密钥来恢复Session这种情况下不需要完全握手。也叫作SSL会话恢复。后面会有介绍。加密套件客户端会给服务器发送自己已经知道的密码套件列表这是由客户按优先级排列的但完全由服务器来决定发送与否。TLS中使用的密码套件有一种标准格式。上面的报文中客户端发送了74套加密套件。服务端会从中选出一种来作为双方共同的加密套件。压缩方法为了减少带宽可以进行压缩。但从成功攻击TLS的事例中来看其中使用压缩时的攻击可以捕获到用HTTP头发送的参数这个攻击可以劫持Cookie这个漏洞我们称为CRIME。从TLS 1.3开始协议就禁用了TLS压缩。扩展包其他参数如服务器名称填充支持的签名算法等可以作为扩展名使用。这些是客户端问候的一部分如果已收到客户端问候接下来就是服务器的确认服务器将发送服务器问候。ServerHello收到客户端问候之后服务器必须发送服务器问候信息服务器会检查指定诸如TLS版本和算法的客户端问候的条件如果服务器接受并支持所有条件它将发送其证书以及其他详细信息否则服务器将发送握手失败消息。如果接受第二步是服务端向客户端发送 Server Hello 消息这个消息会从 Client Hello 传过来的 Support Ciphers 里确定一份加密套件这个套件决定了后续加密和生成摘要时具体使用哪些算法另外还会生成一份随机数Random2。注意至此客户端和服务端都拥有了两个随机数Random1 Random2这两个随机数会在后续生成对称秘钥时用到。图ServerHello报文抓包ServerHello中涉及到的具体参数服务器版本Version服务器会选择客户端支持的最新版本。服务器随机数Random服务器和客户端都会生成32字节的随机数。用来创建加密密钥。加密套件服务器会从客户端发送的加密套件列表中选出一个加密套件。会话IDSession ID服务器将约定的Session参数存储在TLS缓存中并生成与其对应的Session id。它与Server Hello一起发送到客户端。客户端可以写入约定的参数到此Session id并给定到期时间。客户端将在Client Hello中包含此id。如果客户端在此到期时间之前再次连接到服务器则服务器可以检查与Session id对应的缓存参数并重用它们而无需完全握手。这非常有用因为服务器和客户端都可以节省大量的计算成本。在涉及亚马逊和谷歌等流量巨大的应用程序时这种方法存在缺点。每天都有数百万人连接到服务器服务器必须使用Session密钥保留所有Session参数的TLS缓存。这是一个巨大的开销。为了解决这个问题在扩展包里加入了Session Tickets, 在这里客户端可以在client hello中指定它是否支持Session Ticket。然后服务器将创建一个新的会话票证(Session Ticket)并使用只有服务器知道的经过私钥加密的Session参数。它将存储在客户端上因此所有Session数据仅存储在客户端计算机上但Ticket仍然是安全的因为该密钥只有服务器知道。此数据可以作为名为Session Ticket的扩展包含在Client Hello中。压缩算法如果支持服务器将同意客户端的首选压缩方法。扩展包这个阶段之后客户端服务端知道了下列内容SSL版本密钥交换、信息验证和加密算法压缩方法有关密钥生成的两个随机数。SSL建立第二阶段服务器向客户端发送消息。图SSL建立第二阶段报文交换示意图服务器启动SSL握手第2阶段是本阶段所有消息的唯一发送方客户机是所有消息的唯一接收方。该阶段分为4步证书服务器将数字证书和到根CA整个链发给客户端使客户端能用服务器证书中的服务器公钥认证服务器。服务器密钥交换可选这里视密钥交换算法而定证书请求服务端可能会要求客户自身进行验证。服务器握手完成第二阶段的结束第三阶段开始的信号Certificate消息可选—第一次建立必须要有证书一般情况下除了会话恢复时不需要发送该消息在SSL握手的全流程中都需要包含该消息。消息包含一个X.509证书证书中包含公钥发给客户端用来验证签名或在密钥交换的时候给消息加密。这一步是服务端将自己的证书下发给客户端让客户端验证自己的身份客户端验证通过后取出证书中的公钥。图服务器给客户端发送的证书报文Server Key Exchange可选根据之前在ClientHello消息中包含的CipherSuite信息决定了密钥交换方式例如RSA或者DH因此在Server Key Exchange消息中便会包含完成密钥交换所需的一系列参数。图Server Key Exchange报文因为这里是DH算法所以需要发送服务器使用的DH参数。RSA算法不需要这一步。在Diffie-Hellman中客户端无法自行计算预主密钥; 双方都有助于计算它因此客户端需要从服务器获取Diffie-Hellman公钥。由上图可知此时密钥交换也由签名保护。Certificate Request可选——可以是单向的身份认证也可以双向认证这一步是可选的如果在对安全性要求高的常见可能用到。服务器用来验证客户端。服务器端发出Certificate Request消息要求客户端发他自己的证书过来进行验证。该消息中包含服务器端支持的证书类型RSA、DSA、ECDSA等和服务器端所信任的所有证书发行机构的CA列表客户端会用这些信息来筛选证书。Server Hello Done该消息表示服务器已经将所有信息发送完毕接下来等待客户端的消息。图Server Hello Done报文SSL建立第三阶段客户端收到服务器发送的一系列消息并解析后将本端相应的消息发送给服务器。图SSL建立第三阶段报文交换示意图客户机启动SSL握手第3阶段是本阶段所有消息的唯一发送方服务器是所有消息的唯一接收方。该阶段分为3步证书可选为了对服务器证明自身客户要发送一个证书信息这是可选的在IIS中可以配置强制客户端证书认证。客户机密钥交换Pre-master-secret这里客户端将预备主密钥发送给服务端注意这里会使用服务端的公钥进行加密。证书验证可选对预备秘密和随机数进行签名证明拥有a证书的公钥。Certificate可选如果在第二阶段服务器端要求发送客户端证书客户端便会在该阶段将自己的证书发送过去。服务器端在之前发送的Certificate Request消息中包含了服务器端所支持的证书类型和CA列表因此客户端会在自己的证书中选择满足这两个条件的第一个证书发送过去。若客户端没有证书则发送一个no_certificate警告。Client Key exchange根据之前从服务器端收到的随机数按照不同的密钥交换算法算出一个pre-master发送给服务器服务器端收到pre-master算出main master。而客户端当然也能自己通过pre-master算出main master。如此以来双方就算出了对称密钥。如果是RSA算法会生成一个48字节的随机数然后用server的公钥加密后再放入报文中。如果是DH算法这是发送的就是客户端的DH参数之后服务器和客户端根据DH算法各自计算出相同的pre-master secret.图Clinet Key exchange报文本消息在给服务器发送的过程中使用了服务器的公钥加密。服务器用自己的私钥解密后才能得到pre-master key.向服务器证明自己的确持有客户端证书私钥。Certificate verify可选只有在客户端发送了自己证书到服务器端这个消息才需要发送。其中包含一个签名对从第一条消息以来的所有握手消息的HMAC值用master_secret进行签名。SSL建立第四阶段完成握手协议建立SSL连接。图SSL建立第四阶段报文交换示意图客户机启动SSL握手第4阶段使服务器结束。该阶段分为4步前2个消息来自客户机后2个消息来自服务器。建立起一个安全的连接客户端发送一个Change Cipher Spec消息并且把协商得到的CipherSuite拷贝到当前连接的状态之中。然后客户端用新的算法、密钥参数发送一个Finished消息这条消息可以检查密钥交换和认证过程是否已经成功。其中包括一个校验值对客户端整个握手过程的消息进行校验。服务器同样发送Change Cipher Spec消息和Finished消息。握手过程完成客户端和服务器可以交换应用层数据进行通信。ChangeCipherSpec编码改变通知表示随后的信息都将用双方商定的加密方法和密钥发送ChangeCipherSpec是一个独立的协议体现在数据包中就是一个字节的数据用于告知服务端客户端已经切换到之前协商好的加密套件Cipher Suite的状态准备使用之前协商好的加密套件加密数据并传输了。图Cipher Spec Message报文是一条事件消息。Clinet Finished:客户端握手结束通知, 表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值用来供服务器校验使用HMAC算法计算收到和发送的所有握手消息的摘要然后通过RFC5246中定义的一个伪函数PRF计算出结果加密后发送。此数据是为了在正式传输应用数据之前对刚刚握手建立起来的加解密通道进行验证。Server Finished:服务端握手结束通知。使用私钥解密加密的Pre-master数据基于之前(Client Hello 和 Server Hello)交换的两个明文随机数 random_C 和 random_S计算得到协商密钥:enc_keyFuc(random_C, random_S, Pre-Master);计算之前所有接收信息的 hash 值然后解密客户端发送的 encrypted_handshake_message验证数据和密钥正确性;发送一个 ChangeCipherSpec告知客户端已经切换到协商过的加密套件状态准备使用加密套件和 Session Secret加密数据了服务端也会使用 Session Secret 加密一段 Finish 消息发送给客户端以验证之前通过握手建立起来的加解密通道是否成功。根据之前的握手信息如果客户端和服务端都能对Finish信息进行正常加解密且消息正确的被验证则说明握手通道已经建立成功接下来双方可以使用上面产生的Session Secret对数据进行加密传输了。消息验证代码HMAC和TLS数据完整性当服务器或客户端使用主密钥加密数据时它还会计算明文数据的校验和哈希值这个校验和称为消息验证代码MAC。然后在发送之前将MAC包含在加密数据中。密钥用于从数据中生成MAC以确保传输过程中攻击者无法从数据中生成相同的MAC故而MAC被称为HMAC哈希消息认证码。另一方面在接收到消息时解密器将MAC与明文分开然后用它的密钥计算明文的校验和并将其与接收到的MAC进行比较如果匹配那我们就可以得出结论数据在传输过程中没有被篡改。十、验证证书链、验签业务数据过程对应的报文流程如下收到 Leaf 证书和业务数据 ↓ 1. 验证证书链 ↓ ROOT 公钥验证 SUB1 SUB1 公钥验证 SUB2 SUB2 公钥验证 Leaf ↓ 2. 检查 Leaf 证书 ↓ 有效期、用途、身份、是否吊销等 ↓ 3. 从 Leaf 证书取出 Leaf 公钥 ↓ 4. 验证业务数据签名 ↓ 接受业务数据两步证明的内容不同Leaf 证书验证成功 这个 Leaf 公钥确实属于被 CA 认证的身份 业务签名验证成功 发送方确实持有该 Leaf 公钥对应的私钥 并且业务数据没有被修改如果只验证业务签名不验证证书链会有问题。攻击者可以自己生成密钥对 自己签业务数据 把自己的公钥放进伪造证书签名当然能通过但这个公钥并没有经过可信 CA 认证。所以完整判断必须是证书链可信 AND Leaf 证书有效 AND 业务签名有效证书中的 CA 签名Certificate报文携带Leaf 证书 SUB2 证书 SUB1 证书Leaf 证书内部的签名是SUB2 私钥 ↓ 签名 Leaf 证书TLS 握手签名以 TLS 1.2 的ECDHE_ECDSA为例ClientHello ServerHello Certificate ServerKeyExchange ServerHelloDone两个关键报文分别是Certificate Leaf 证书 中间证书链 ServerKeyExchange ECDHE 临时公钥 Leaf 私钥生成的签名服务器签名的大致内容是ClientRandom ServerRandom ECDHE 参数 ECDHE 临时公钥 ↓ 使用 Leaf 私钥签名客户端的验证过程1. 从 Certificate 中验证证书链 2. 从 Leaf 证书中取出 Leaf 公钥 3. 使用 Leaf 公钥验证 ServerKeyExchange 中的签名因此 TLS 1.2 中可以记成Certificate 证明 Leaf 公钥属于谁 ServerKeyExchange 证明服务器确实持有对应的 Leaf 私钥TLS 1.3 中没有ServerKeyExchange对应关系变成Certificate 携带证书链 CertificateVerify 携带 Leaf 私钥对握手内容生成的签名TLS 建联后不会用 Leaf 私钥给每个业务报文签名。TLS 的过程是建联阶段 Leaf 私钥签署 TLS 握手内容 ↓ 证明服务器持有 Leaf 私钥 ↓ 通过 ECDHE 生成共享密钥建联完成后业务数据 ↓ 使用 TLS 对称会话密钥进行 AEAD 加密 ↓ 密文 完整性认证标签也就是说TLS 握手阶段使用 Leaf 私钥 TLS 业务传输阶段使用协商出的对称会话密钥这样做是因为对称加密速度更快适合持续传输数据。TLS 的AES-GCM等 AEAD 算法已经可以保护数据机密性数据完整性当前 TLS 会话内的数据来源什么时候还需要业务签名如果 V2G 应用协议明确要求某些业务报文具有独立数字签名那么仍然需要签名V2G 业务数据 ↓ 使用业务私钥签名 业务数据 业务签名 ↓ TLS 对称加密 发送接收端TLS 验证并解密 ↓ 使用业务证书公钥验证业务签名而且这里的业务私钥不一定是 TLS Leaf 私钥。例如可能分别使用TLS 服务器证书私钥 用于认证 TLS 服务器和建立安全通道 合同证书私钥 用于签署要求数字签名的 PnC/V2G 业务数据TLS Leaf 私钥主要用于 TLS 身份认证TLS 建联后使用对称会话密钥保护报文。只有应用协议明确要求时才额外使用相应的业务私钥签署特定 V2G 报文。

相关新闻