1. TLS 握手基础:从协议概览到密码套件协商

各位同学好,我是老周。今天咱们正式进入《TLS会话恢复机制与性能调优》的第一章。说实话,TLS握手是整个安全通信的基石,你后面要理解会话恢复、0-RTT这些高级特性,都得先把握手吃透。这一章我会带着大家把TLS协议的全貌、1.2和1.3的握手流程、密码套件协商这些基础过一遍。

1.1 TLS协议概述

TLS,全称Transport Layer Security,中文叫传输层安全协议。它的前身是SSL,现在大家基本都用TLS这个叫法了。TLS工作在传输层之上、应用层之下,说白了就是在TCP上面加了一层安全壳。

这个协议主要干三件事:

  • 身份认证——确认你连接的服务端是真的,不是冒牌货
  • 密钥协商——双方安全地商量出一个对称密钥
  • 数据加密——用商量好的密钥加密后续通信内容

我个人习惯把TLS比作一个「安全握手协议」。你想想看,两个人见面先握手确认身份,然后悄悄约定一个暗号,之后就用暗号加密交流。TLS本质上就是这个逻辑。

核心要点:TLS不负责传输数据,它只负责让传输变得安全。真正的数据传输还是交给TCP去做。

1.2 TLS 1.2 完整握手流程

TLS 1.2是目前生产环境中使用最广泛的版本。虽然1.3已经出来好几年了,但很多老系统还在跑1.2。我在项目中遇到过不少客户,升级到1.3时因为兼容性问题回退到1.2,所以这个版本你必须掌握。

完整的TLS 1.2握手需要2-RTT(两次往返),流程如下:

  1. ClientHello:客户端发消息,告诉服务端自己支持的TLS版本、密码套件列表、随机数等
  2. ServerHello:服务端从客户端列表里选一个密码套件,发回自己的随机数
  3. Certificate:服务端发送自己的数字证书(含公钥)
  4. ServerKeyExchange:如果需要,服务端发送密钥交换参数(比如DH参数)
  5. ServerHelloDone:服务端说「我发完了」
  6. ClientKeyExchange:客户端发送密钥交换参数(比如DH公钥)
  7. ChangeCipherSpec:客户端说「我要开始加密了」
  8. Finished:客户端发送加密后的握手摘要,用于完整性校验
  9. ChangeCipherSpec:服务端也说「我要开始加密了」
  10. Finished:服务端发送加密后的握手摘要

嗯,这里要注意,TLS 1.2的握手消息是明文传输的,只有ChangeCipherSpec之后的消息才加密。这就意味着,如果中间人想搞破坏,在握手阶段就能看到你协商了啥。

避坑指南:我曾经帮一个客户排查性能问题,发现每次连接都要做完整握手,延迟高达200ms。后来一看,原来是服务端没开会话缓存。TLS 1.2的完整握手确实慢,2-RTT在跨洋链路上就是实打实的延迟。

1.3 TLS 1.3 握手改进

TLS 1.3是2018年发布的,它最大的改进就是——把握手从2-RTT砍到了1-RTT。怎么做到的?说白了就是「合并消息」和「精简流程」。

我们来看看TLS 1.3的握手流程:

  1. ClientHello:客户端直接带上自己的密钥交换参数(比如DH公钥)和猜测的密码套件
  2. ServerHello + 证书 + 服务端参数 + Finished:服务端一次性回复所有内容
  3. 客户端Finished:客户端确认握手完成

你看,TLS 1.3把服务端的多个消息合并成了一个Flight。而且,它去掉了ChangeCipherSpec这个冗余消息,也砍掉了那些不安全的密码套件。

为什么会这样?因为TLS 1.3的设计者发现,1.2的很多步骤其实可以并行处理。比如证书和密钥交换参数,没必要分开发送。

对比项 TLS 1.2 TLS 1.3
握手RTT 2-RTT 1-RTT
支持的密码套件 37种(含不安全) 5种(仅安全)
ChangeCipherSpec 需要 移除
会话恢复 Session ID / Session Ticket PSK + 0-RTT
前向安全性 可选 强制

个人经验:我建议新项目直接上TLS 1.3。虽然1.2还能用,但1.3在性能和安全性上都更优。唯一要注意的是,有些老旧的客户端(比如Android 4.x)不支持1.3,这时候需要做版本协商降级。

1.4 密码套件协商

密码套件,英文叫Cipher Suite,它是一组算法的组合。TLS握手时,客户端和服务端要商量好用哪一套算法来干活。

一个典型的TLS 1.2密码套件长这样:

TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

拆开来看:

  • TLS:协议前缀
  • ECDHE:密钥交换算法(椭圆曲线Diffie-Hellman临时密钥)
  • RSA:身份认证算法
  • AES_256_GCM:对称加密算法(AES-256,GCM模式)
  • SHA384:消息认证码算法(HMAC-SHA384)

到了TLS 1.3,密码套件简化了很多,只保留5个:

TLS_AES_128_GCM_SHA256
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_CCM_SHA256
TLS_AES_128_CCM_8_SHA256

你看,TLS 1.3的密码套件不再包含密钥交换和身份认证算法,因为这两部分被独立出来了。这样设计的好处是,密码套件只负责加密和完整性,密钥交换和认证由握手协议单独处理。

协商过程其实很简单:客户端在ClientHello里列出自己支持的所有密码套件(按优先级排序),服务端从里面选一个自己也能支持的。如果服务端一个都选不出来,那就握手失败。

避坑指南:我曾经遇到过一个问题,客户端和服务端都支持TLS 1.2,但握手就是失败。查了半天,发现客户端只支持ECDHE密钥交换,而服务端证书是RSA的,但服务端没配ECDSA证书。说白了,密码套件里的每个组件都得匹配上,缺一个都不行。

本章知识体系

下面这张图展示了本章的核心知识结构,我把它画成了SVG,方便大家对照理解:

TLS握手基础 — 知识体系 TLS握手基础 TLS协议概述 TLS 1.2完整握手 TLS 1.3握手改进 密码套件协商 身份认证 密钥协商 数据加密 2-RTT延迟 明文握手 37种密码套件 1-RTT延迟 合并消息 5种安全套件 密钥交换算法 身份认证算法 对称加密算法 TLS 1.3相比1.2,握手延迟降低50%,密码套件精简86% 但兼容性要求更高,需要做好版本协商降级策略

这张图把本章的四个核心模块串起来了。从TLS协议概述出发,分别展开TLS 1.2和1.3的握手流程,最后落到密码套件协商。大家可以看到,TLS 1.3在延迟和安全性上都有明显优势,但密码套件的选择范围也大幅缩小了。

好了,第一章的内容就到这里。记住,握手是TLS性能的起点,后面讲会话恢复和0-RTT时,你会反复用到今天学的这些知识。