6.1 TLS 协议:从 SSL 到 TLS 1.3 的握手演进


6.1 TLS 协议:从 SSL 到 TLS 1.3 的握手演进

本节摘要:TLS 是全球部署规模最大的密码协议,它的每个版本号都是一份事故清单的回应:BEAST 与 POODLE 处死了 CBC,Lucky13 处死了 MAC 后加密,DROWN 处死了版本混搭,Heartbleed 教会世界"实现也是攻击面"。2018 年定稿的 TLS 1.3 用一轮握手、只留 AEAD 与临时密钥协商,把本书的工程铁律写进了协议本体。

一次握手,前五章同台

先看清这台机器的完整运转。以 TLS 1.3 为例,一次握手在两个来回内完成四件事:

  • ClientHello:客户端递出协议版本、支持的加密套件清单、随机数,以及密钥共享——一个 ECDHE 临时公钥。协商材料从第一跳就开始传输,这是一轮握手的关键设计;
  • ServerHello 与证书:服务器选定套件、回敬自己的临时公钥,随后递出证书链(6.2 节),并用长期密钥对整个握手过程签名——证明"这份密钥交换确实出自证书主人";
  • 密钥推导:双方各自用 ECDHE 私钥算出预主密钥,再经 HKDF(以哈希为内核的密钥推导函数,第 5 章的哈希在此当值)分层导出握手密钥与应用流量密钥。握手全程的 Transcript 哈希被卷入推导,协商内容不可中途调包;
  • Finished 与切轨:双方互发 Finished 消息(对 Transcript 的认证标签)完成互认,之后所有数据进入记录层,由 AES-GCM 或 ChaCha20-Poly1305 以 AEAD 方式承载。

注意分工的精确性:ECDHE 负责协商与前向安全(4.3 节),签名与证书负责认证(4.5、6.2 节),HKDF 负责把一个种子密钥展开成多把用途密钥(5.1 节),AEAD 负责机密性与完整性合一(3.3、3.5 节)。一次握手,前五章同台。

图:TLS 1.2 与 TLS 1.3 的握手对比

图:TLS 1.2 与 TLS 1.3 的握手对比

二、事故清单:每个被删套件背后都站着一场攻击

TLS 的演化史几乎可以按"攻击驱动的减法"来读,这份清单值得整段记住,因为它是密码工程最贵的一套学费:

  • BEAST(2011):TLS 1.0 的 CBC 使用可预测 IV,攻击者可逐字节猜出 Cookie——CBS 链上随机化 IV 的修复进入 1.2;
  • Lucky13(2013):MAC 后加密的组装让填充错误与 MAC 错误的解密耗时略有差异,统计足够多连接即可恢复明文——时序侧信道打进协议层,直接推动 AEAD 路线;
  • POODLE(2014):SSL 3.0 的 CBC 填充格式不校验内容,降级到旧版本后可解密 Cookie——"版本混搭"本身成为攻击面,强制降级保护机制出台;
  • RC4 偏差(2013):3.4 节的老案,TLS 场景下 2²⁶ 个连接量级即可恢复 Cookie,RFC 7465 禁用;
  • Logjam(2015):出口级 512 位弱 DH 参数被降级攻击激活,预计算对常用 1024 位素数同样致命——呼应 4.3 节"参数要新、素数要大";
  • DROWN(2016):同一证书同时挂在 SSLv2 与 TLS 上,旧协议被打穿后新协议陪葬——"禁用旧版本"不是洁癖是义务;
  • Heartbleed(2014):严格说是实现事故而非协议缺陷——心跳扩展的长度字段未校验导致越界读内存,密钥与 Cookie 可被批量舀出。它把"实现审计与 fuzzing"写进了部署清单。

工程侧的应对已经有标准动作:只启用 TLS 1.2 与 1.3(1.0/1.1 已于 2021 年被 IETF 正式废弃)、套件白名单只留 AEAD、证书链与 OCSP 装订配齐、用现成库且跟进安全版本。下面的代码是 Python 服务端禁用旧版本的典型姿势:

import ssl ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) # 由库协商最优版本 ctx.minimum_version = ssl.TLSVersion.TLSv1_2 # 禁掉 TLS 1.0/1.1 ctx.options |= ssl.OP_NO_COMPRESSION # 压缩曾致 CRIME 攻击,直接关 # 证书与私钥挂载后即可 serve;套件选择交给库的默认白名单(仅 AEAD) print(ctx.minimum_version, ctx.maximum_version) # 确认边界生效

⚠️ 常见坑:以为"上了 HTTPS 就安全了"。TLS 只保护传输中的数据,两端存储与日志的泄露、0-RTT 重放、降级配置错误都不在它的管辖范围。协议是防线的一段,不是全部。

排错速查:握手失败的七种原因

一,系统时钟偏差——证书"未生效"最常见的原因,虚拟机休眠恢复后尤其多发;二,服务器漏发中间证书,信任链在根与叶之间断掉;三,客户端过旧,不支持服务器仅存的 AEAD 套件;四,服务器配置过严,把合法的旧客户端整体拒之门外;五,防火墙或安全软件在本地拦截并重签证书,浏览器报"颁发机构无效";六,域名与证书的 SAN 不匹配,多见于测试环境借用生产证书;七,协议版本被某一侧硬性禁用,两端没有交集。

排查工具:openssl 的 s_client 子命令能拉出完整握手过程与证书链,浏览器的安全面板能显示协商到的版本与套件,二者对照即可把七种原因收敛成一两种。运维纪律同样重要:证书到期监控、禁用清单随版本更新、变更前在灰度环境跑一遍握手回归——TLS 事故多在变更窗口爆发,而不是在攻击里。

常见问答:为什么不允许降级

问:老设备实在不支持新协议,允许"协商不上就退回旧版本"不行吗?这正是 POODLE 与 DROWN 教训的来源:降级通道一旦存在,攻击者可以主动制造协商失败,把双方硬推回弱版本。正确的兼容姿势是维护两套并行端点或升级客户端,而不是在单一握手里留回退路径。版本协商的完整性由 Finished 消息的抄本哈希兜底,任何中途篡改协商结果的尝试都会在最后一步校验中现形——这条设计在 1.3 中被贯彻得最彻底。

本节要点回顾

  • 握手分工:ECDHE 协商加前向安全、证书加签名做认证、HKDF 分层推导、AEAD 承载数据——前五章零件各就各位;
  • 1.3 的减法:删除静态 RSA、CBC、RC4 与压缩,握手压到一轮,密钥共享前移是提速的关键;
  • 事故即课纲:BEAST、Lucky13、POODLE、Logjam、DROWN 分别对应模式、次序、降级、弱参数与版本混搭六类错误;
  • 0-RTT 边界:早数据低延迟但可重放且无前向安全,只用于幂等请求。

协议解决了"两台机器如何互信通信",但"服务器公钥凭什么可信"还悬着。下一节拆证书与信任链——公钥的身份证体系。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U