一、最大化兼容性
由于1.1、1.2等协议已经出现了很多年,很多应用软件、中间代理等(官方被称为“MiddleBox”)只认老的记录协议格式,就像是HTTP/3抛弃了TCP作为底层的原因类似。更新改造很困难,甚至是不可能的。
为了保证这些被广泛部署的“老设备”能够继续使用,避免新协议带来的“冲击”,TLS1.3 不得不做出妥协,保持现有的记录格式不变,通过“伪装”来实现兼容,使得 TLS1.3 看上去“像是”TLS1.2。
在TLS1.3中,用了一个新的“扩展协议”(Extension Protocol),它有点“补充条款”的意思,通过在记录末尾添加一系列的“扩展字段”来增加新的功能,老版本的 TLS 不认识它可以直接忽略,这就实现了“后向兼容”。
Handshake Protocol: Client Hello Version: TLS 1.2 (0x0303 Extension: supported_versions (len=11 Supported Version: TLS 1.3 (0x0304 Supported Version: TLS 1.2 (0x0303
TLS1.3 利用扩展实现了许多重要的功能,比如“supported_groups”、“key_share”、“signature_algorithms”、“server_name”等,这些等后面用到的时候再说。
二、强化安全
- 伪随机数函数由 PRF 升级为 HKDF(HMAC-based Extract-and-Expand Key Derivation Function);
- 明确禁止在记录协议里使用压缩;
- 废除了 RC4、DES 对称加密算法;
- 废除了 ECB、CBC 等传统分组模式;
- 废除了 MD5、SHA1、SHA-224 摘要算法;
- 废除了 RSA、DH 密钥交换算法和许多命名曲线。
嗯……了解下就行了。
AES、ChaCha20对称加密算法,分组模式只能用 AEAD 的 GCM、CCM 和 Poly1305,摘要算法只能用 SHA256、SHA384,密钥交换算法只有 ECDHE 和 DHE,椭圆曲线也被“砍”到只剩 P-256 和 x25519 等 5 种。
前向安全”(Forward Secrecy)。什么意思呢?
今日截获,明日破解”。
三、提升性能
HTTPS 建立连接时除了要做 TCP 握手,还要做 TLS 握手,在 1.2 中会多花两个消息往返(2-RTT),可能导致几十毫秒甚至上百毫秒的延迟,在移动网络中延迟还会更严重。
其实具体的做法还是利用了扩展。客户端在“Client Hello”消息里直接用“supported_groups”带上支持的曲线,比如 P-256、x25519,用“key_share”带上曲线对应的客户端公钥参数,用“signature_algorithms”带上签名算法。
其实夸张一点,所有的数据交换,来回一次就够了,只需要一个往返,你品品?
四、握手分析
首先还是TCP的三次握手,握手建立TCP连接后,浏览器还是首先发个“Client Hello”,因为 1.3 的消息兼容 1.2,所以开头的版本号、支持的密码套件和随机数(Client Random)结构都是一样的(不过这时的随机数是 32 个字节)。
Handshake Protocol: Client Hello Version: TLS 1.2 (0x0303 Random: cebeb6c05403654d66c2329… Cipher Suites (18 suites Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301 Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303 Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302 Extension: supported_versions (len=9 Supported Version: TLS 1.3 (0x0304 Supported Version: TLS 1.2 (0x0303 Extension: supported_groups (len=14 Supported Groups (6 groups Supported Group: x25519 (0x001d Supported Group: secp256r1 (0x0017 Extension: key_share (len=107 Key Share extension Client Key Share Length: 105 Key Share Entry: Group: x25519 Key Share Entry: Group: secp256r1
注意“Client Hello”里的扩展,“supported_versions”表示这是 TLS1.3,“supported_groups”是支持的曲线,“key_share”是曲线对应的参数。
Handshake Protocol: Server Hello Version: TLS 1.2 (0x0303 Random: 12d2bce6568b063d3dee2… Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301 Extension: supported_versions (len=2 Supported Version: TLS 1.3 (0x0304 Extension: key_share (len=36 Key Share extension Key Share Entry: Group: x25519, Key Exchange length: 32
表面上看和 TLS1.2 是一样的,重点是后面的扩展。“supported_versions”里确认使用的是 TLS1.3,然后在“key_share”扩展带上曲线和对应的公钥参数。
在算出主密钥后,服务器立刻发出“Change Cipher Spec”消息,比 TLS1.2 提早进入加密通信,后面的证书等就都是加密的了,减少了握手时的明文信息泄露。
这两个“Hello”消息之后,客户端验证服务器证书,再发“Finished”消息,就正式完成了握手,开始收发 HTTP 报文。
五、小结
其实这篇文章和上一篇文章的重点都在于图中,大家要好好消化。要注意TLS1.3相比于TLS1.2有哪些不同点,其实核心就是通过扩展协议来提前把需要参数交换,嗯……就这么简单。