TLS 协议基础:HTTPS 与 TLS 关系、握手过程、1.2 与 1.3 差异

各位好,我是老周。做安全这行十几年,TLS 算是打交道最多的协议之一。很多人觉得 HTTPS 就是「网站加个锁」,但锁里面到底怎么拧的,很少有人细究。这一章咱们就把 TLS 的基础捋一遍,尤其是 1.2 和 1.3 握手到底差在哪。

HTTPS 与 TLS:到底谁包着谁?

先说个容易混淆的点。HTTPS 不是协议,它是 HTTP 跑在 TLS 之上。说白了,HTTP 是快递员,TLS 是防拆封的保险箱。快递员把货物放进保险箱,再送到你手上。你用钥匙打开保险箱,才能拿到货物。

关键关系:HTTPS = HTTP + TLS。没有 TLS 就没有 HTTPS,TLS 才是真正干活的那个。

我在项目里见过不少新人,抓包看到 Client Hello 就开始喊「HTTPS 握手」,其实那是 TLS 握手。HTTP 的请求得等 TLS 隧道建好之后才能发。你想想看,如果连安全通道都没搭起来,谁敢把密码扔出去?

TLS 握手:一次双向验证的「对暗号」

TLS 握手的目的很简单:商量加密算法、交换密钥、验证对方身份。整个过程大概分四步——当然,1.2 和 1.3 的步骤数不一样,咱们后面细说。

1.2 握手流程(经典款)

  1. Client Hello:客户端发个打招呼消息,带上支持的 TLS 版本、密码套件列表、随机数。
  2. Server Hello:服务器从中选一套,发回自己的证书和随机数。
  3. Certificate & Key Exchange:服务器发证书(必要时发中间证书链),如果使用 DH 密钥交换,还会发公钥参数。
  4. Client Key Exchange:客户端用服务器公钥加密一个预主密钥(pre-master secret)发过去。
  5. Change Cipher Spec & Finished:双方各自算出会话密钥,发 Finished 消息确认后续通信将加密。

嗯,这里要注意:1.2 的握手需要两个 Round Trip(2-RTT)。每次你来我往都耗时,尤其是跨洋连接,延迟一下就上去了。

1.3 握手流程(加速版)

  1. Client Hello:客户端不仅打招呼,还直接附带了密钥交换的公开参数(比如 ECDHE 的公钥)。
  2. Server Hello:服务器回复,同时带上自己的公钥参数和加密的证书。
  3. Finished:双方可以直接算密钥,发 Finished。整个握手只需要 1-RTT。

我建议:新项目直接上 TLS 1.3。1.2 的兼容性虽好,但 1.3 的握手延迟优势实在太大,尤其对移动端或 IoT 场景,少一次往返就少几百毫秒。

避坑:我曾经在升级 1.2 到 1.3 时,没注意中间件(比如某些老款 F5)不支持 1.3 的密码套件,导致握手失败。升级前一定要核对证书链和密码套件兼容性。

TLS 1.2 vs 1.3:一张表说清核心差异

对比维度 TLS 1.2 TLS 1.3
握手 RTT 2 次(2-RTT) 1 次(1-RTT),支持 0-RTT
密码套件 几十种,包含 RSA、DH、DHE、ECDHE 等 仅保留 AEAD 密码(如 AES-GCM、ChaCha20-Poly1305),移除 RSA 密钥交换
证书传输 明文传输证书 证书加密传输(ServerHello 之后)
密钥协商算法 支持 RSA、DH、ECDH 只支持 (EC)DHE,保证前向安全性
签名算法 支持 SHA-1、SHA-256 等 移除 SHA-1,只允许 SHA-256 及以上
会话恢复 Session ID 或 Session Ticket PSK + Ticket,支持 0-RTT

这张表我建议你收藏。每次跟开发团队扯 TLS 版本升级时,直接甩过去就行。1.3 砍掉了好多老旧的密码套件,这背后是「前向安全性」的硬要求。说白了,如果服务端密钥泄露,之前的通信也不会被解密——1.2 里用 RSA 做密钥交换就做不到这点。

SVG:TLS 握手流程对比图

画一张图,把 1.2 和 1.3 的握手步骤放在一起,差异一目了然。左边是 1.2(2-RTT),右边是 1.3(1-RTT),中间用箭头表示时间顺序。

TLS 1.2 vs TLS 1.3 握手流程对比 TLS 1.2(2-RTT) 1. Client Hello(随机数+密码套件列表) 2. Server Hello(证书+DH公钥) 3. Certificate + ServerKeyExchange 4. ClientKeyExchange(预主密钥) 5. ChangeCipherSpec + Finished TLS 1.3(1-RTT) 1. Client Hello(随机数+密钥共享+密码套件) 2. Server Hello(DH公钥+加密证书) 3. Finished(加密握手完成,1-RTT) 关键区别 1.2 需要 2 次往返才能生成会话密钥,证书明文传输 1.3 只需 1 次往返,证书加密传输,且强制前向安全 横轴对比:步骤数减少一半,延迟降低

一个小工具:用 OpenSSL 查看 TLS 版本协商

光说不练假把式。我用 OpenSSL 来验证一下实际连接的版本。假设你想看某个 HTTPS 网站到底用了 1.2 还是 1.3:

openssl s_client -connect example.com:443 -tls1_3 2>/dev/null | grep "New, TLSv1.3"

如果输出为空,说明服务端不支持 1.3。再试试 1.2:

openssl s_client -connect example.com:443 -tls1_2 2>/dev/null | grep "New, TLSv1.2"

我的习惯:每次上线前,我都会用这条命令扫一遍目标站点的 TLS 配置。之前有个客户,证书明明是 SHA-256 签的,但服务器却只开了 1.2 且支持 RSA 交换,差点被当成弱配置拦下。后来加了 -tls1_3 才发现是版本没开。

总结一下今天的重点

  • HTTPS 是 HTTP over TLS,TLS 才是安全通道的建造者。
  • 握手流程从 1.2 的 2-RTT 精简到 1.3 的 1-RTT,并且强制前向安全。
  • 1.3 砍掉了 RSA 密钥交换和 SHA-1 签名,只保留 AEAD 加密套件。
  • 实际排查时,用 s_client 一把就能看出服务端支持哪些版本。

嗯,基础先到这。下次遇到 TLS 握手失败,你心里应该有个谱了——查版本、查密码套件、查证书,流程跑一遍基本能定位。