016: TLS 1.3 做了哪些改进?
TLS 1.2 虽然存在了 10 多年,经历了无数的考验,但历史的车轮总是不断向前的,为了获得更强的安全、更优秀的性能,在2018年
就推出了 TLS1.3,对于TLS1.2
做了一系列的改进,主要分为这几个部分:强化安全、提高性能。
强化安全
在 TLS1.3 中废除了非常多的加密算法,最后只保留五个加密套件:
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
- TLS_AES_128_GCM_SHA256
- TLS_AES_128_GCM_8_SHA256
可以看到,最后剩下的对称加密算法只有 AES 和 CHACHA20,之前主流的也会这两种。分组模式也只剩下 GCM 和 POLY1305, 哈希摘要算法只剩下了 SHA256 和 SHA384 了。
那你可能会问了, 之前RSA
这么重要的非对称加密算法怎么不在了?
我觉得有两方面的原因:
第一、2015年发现了FREAK
攻击,即已经有人发现了 RSA 的漏洞,能够进行破解了。
第二、一旦私钥泄露,那么中间人可以通过私钥计算出之前所有报文的secret
,破解之前所有的密文。
为什么?回到 RSA 握手的过程中,客户端拿到服务器的证书后,提取出服务器的公钥,然后生成pre_random
并用公钥加密传给服务器,服务器通过私钥解密,从而拿到真实的pre_random
。当中间人拿到了服务器私钥,并且截获之前所有报文的时候,那么就能拿到pre_random
、server_random
和client_random
并根据对应的随机数函数生成secret
,也就是拿到了 TLS 最终的会话密钥,每一个历史报文都能通过这样的方式进行破解。
但ECDHE
在每次握手时都会生成临时的密钥对,即使私钥被破解,之前的历史消息并不会收到影响。这种一次破解并不影响历史信息的性质也叫前向安全性。
RSA
算法不具备前向安全性,而 ECDHE
具备,因此在 TLS1.3 中彻底取代了RSA
。
提升性能
握手改进
流程如下:
大体的方式和 TLS1.2 差不多,不过和 TLS 1.2 相比少了一个 RTT, 服务端不必等待对方验证证书之后才拿到client_params
,而是直接在第一次握手的时候就能够拿到, 拿到之后立即计算secret
,节省了之前不必要的等待时间。同时,这也意味着在第一次握手的时候客户端需要传送更多的信息,一口气给传完。
这种 TLS 1.3 握手方式也被叫做1-RTT握手。但其实这种1-RTT
的握手方式还是有一些优化的空间的,接下来我们来一一介绍这些优化方式。
会话复用
会话复用有两种方式: Session ID和Session Ticket。
先说说最早出现的Seesion ID,具体做法是客户端和服务器首次连接后各自保存会话的 ID,并存储会话密钥,当再次连接时,客户端发送ID
过来,服务器查找这个 ID 是否存在,如果找到了就直接复用之前的会话状态,会话密钥不用重新生成,直接用原来的那份。
但这种方式也存在一个弊端,就是当客户端数量庞大的时候,对服务端的存储压力非常大。
因而出现了第二种方式——Session Ticket。它的思路就是: 服务端的压力大,那就把压力分摊给客户端呗。具体来说,双方连接成功后,服务器加密会话信息,用Session Ticket消息发给客户端,让客户端保存下来。下次重连的时候,就把这个 Ticket 进行解密,验证它过没过期,如果没过期那就直接恢复之前的会话状态。
这种方式虽然减小了服务端的存储压力,但与带来了安全问题,即每次用一个固定的密钥来解密 Ticket 数据,一旦黑客拿到这个密钥,之前所有的历史记录也被破解了。因此为了尽量避免这样的问题,密钥需要定期进行更换。
总的来说,这些会话复用的技术在保证1-RTT
的同时,也节省了生成会话密钥这些算法所消耗的时间,是一笔可观的性能提升。
PSK
刚刚说的都是1-RTT
情况下的优化,那能不能优化到0-RTT
呢?
答案是可以的。做法其实也很简单,在发送Session Ticket的同时带上应用数据,不用等到服务端确认,这种方式被称为Pre-Shared Key
,即 PSK。
这种方式虽然方便,但也带来了安全问题。中间人截获PSK
的数据,不断向服务器重复发,类似于 TCP 第一次握手携带数据,增加了服务器被攻击的风险。
总结
TLS1.3 在 TLS1.2 的基础上废除了大量的算法,提升了安全性。同时利用会话复用节省了重新生成密钥的时间,利用 PSK 做到了0-RTT
连接。