10 Aug 2018 by Nick Sullivan.

在过去的五年中,IETF(Internet Engineering Task Force,定义互联网协议的标准机构)一直致力于标准化其最重要的安全协议之一,TLS协议的最新版本。TLS用于保护Web(远不止Web),提供加密并确保每个HTTPS网站和API的真实性。

就在2018年8月10号,TLS协议的最新版本,TLS 1.3(RFC 8446)发布了。这是TLS协议的第一次重大改革,带来了重大的安全性和性能改进。本文深入探讨了TLS 1.3的重要变化及其对互联网安全未来的影响。

TLS协议的进化

Cloudflare提供安全性的一个主要方式是支持网站和API等Web服务启用HTTPS。使用HTTPS(“S”代表安全),浏览器和服务器之间的消息通过加密和已经过身份验证的通道传输。网站通过HTTPS替代HTTP访问,能让用户确信自己访问的内容是网站所提供的原本内容, 并且确信通信是安全的,不会被窃听。互联网发展到今天,在线隐私问题变得更加重要,而这也是如今一个很大的问题。

HTTPS的能保证安全主要依赖的是TLS协议。TLS协议源于九十年代中期,Netscape开发的SSL的协议。到20世纪90年代末,Netscape将SSL交给IETF,IETF将其重命名为TLS,并从此成为该协议的管理者。许多人仍将Web加密称为SSL,即使绝大多数服务已切换到且仅支持TLS。SSL这个术语仍然受到人们的欢迎,Cloudflare的Keyless SSLUniversal SSL等产品也仍然使用这重说法。

在IETF中,协议称为RFC。TLS 1.0是RFC 2246,TLS 1.1是RFC 4346,TLS 1.2是RFC 5246.今天,TLS 1.3发布为RFC 8446. RFC通常按顺序发布,保留46作为RFC编号的一部分是一个很好的传承。

TLS 1.2已经成为过去

*与Ham一样,MC Hammer在90年代很受欢迎

在过去几年中,TLS已经出现了相当多的问题。首先,实现TLS的代码存在问题,包括HeartbleedBERserkgoto fail 等等。这些问题还不是协议的基础问题,其主要是由于缺乏测试。像TLS AttackerProject Wycheproof这样的工具有助于提高TLS实施的稳健性,但TLS面临的更具挑战性的问题与协议本身有关。

TLS由工程师使用数学家的工具设计。SSL时代的许多早期设计决策都是使用最原始的方法,当时人们对如何设计健壮的安全协议不完全理解。也就是说,这不是协议设计者(Paul Kocher,Phil Karlton,Alan Freier,Tim Dierks,Christopher Allen等人)的错,因为整个行业都还在在学习如何正确地做到这一点。在设计TLS时,关于安全认证协议设计的正式论文还需要几年才发布(如Hugo Krawczyk的标志性SIGMA论文)。TLS是90年代的加密方式:它当时意味着很好,看起来很酷,但是现代密码学已经发展的更加强壮了。

许多设计缺陷是使用形式验证(Formal Verification)发现的。学者们试图证明TLS的某些安全属性,但却找到了反例,这些反例被转化为真正的漏洞。这些弱点包括纯理论漏洞(SLOTHCurveSwap),高资源攻击者漏洞(WeakDHLogJamFREAKSWEET32),实用和危险漏洞(POODLEROBOT)。

TLS 1.2很慢

互联网上,加密一直很重要。但从历史上看,只有登陆信息与信用卡信息被加密,使大多数其他数据暴露。在过去几年中,一直存在一个主要趋势,全面启用HTTPS。所有流量都经过HTTPS后,能使我们免受窃听者和注入攻击的影响,但连接的速度却相对较慢。

要使浏览器和Web服务器就密钥达成一致,他们需要交换加密数据。自TLS于1999年标准化以来,在TLS中握手过程中的数据交换基本保持不变。握手需要在发送加密数据之前在浏览器和服务器之间再进行两次往返(或者在会话恢复先前连接时进行一次往返)。与单独的HTTP相比,HTTPS的TLS握手的额外成本导致潜在的问题。这种额外的延迟会对以性能为中心的应用产生负面影响。

定义TLS 1.3

IETF对TLS 1.2的过时设计和两次往返开销不满意,开始着手定义新版本的TLS。2013年8月,Eric Rescorla为新协议制定了一份功能愿望清单:https//www.ietf.org/proceedings/87/slides/slides-87-tls-5.pdf

经过一番辩论后,决定将这个新版本的TLS称为TLS 1.3。推动TLS 1.3设计的主要问题与五年前提出的主要问题大致相同:

  • 减少握手延迟
  • 加密更多的握手消息
  • 提高跨协议攻击的难度
  • 删除旧功能

该规范由志愿者通过开放的设计过程设计,经过四年的勤奋工作和激烈的讨论,TLS 1.3现在处于最终形式:RFC 8446。随着协议的推广使用,新协议将使互联网更快,更多安全。

在这篇博文中,我将重点介绍TLS 1.3与以前版本相比的两个主要优势:安全性和性能。

一些修复

在过去的二十年中,我们已经学到了很多关于如何编写一个安全加密协议的相关知识。从POODLE到Lucky13到SLOTH到LogJam等一系列巧妙命名攻击表明,即使是TLS 1.2也包含了早期加密设计的一些陈旧观点。TLS 1.3的设计目标之一是通过消除潜在危险的设计元素来纠正以前的错误。

修复密钥交换

TLS是所谓的“混合”密码系统。这意味着它同时使用对称密钥加密(加密和解密密钥相同)和公钥加密(加密和解密密钥不同)。混合方案是现互联网上使用的主要加密形式,如SSHIPsecSignalWireGuard等其他协议。在混合密码系统中,公钥密码技术用于在双方之间建立共享密钥,共享密钥用于创建加密交换数据的对称密钥。

实际上,公钥加密是缓慢而且代价较高的(每个操作需要几微秒到几毫秒),对称密钥加密快速且代价小(每个操作都是纳秒级别)。混合加密方案允许您通过仅执行一次公钥加密,以极少的开销发送大量加密数据。TLS 1.3中的大部分工作都是关于改进握手部分,其中公钥用于建立对称密钥。

RSA密钥交换

TLS中公钥是用来建立共享秘密的。使用公钥加密有两种主要方法。其中一种简单的方法是使用公钥加密:一方用另一方的公钥加密共享密钥并发送它。然后另一方使用其私钥解密共享秘密。最后他们生成相同的加密密钥。这种技术于1977年由Rivest,Shamir和Adelman发现,称为RSA密钥交换。在RSA密钥交换中,共享密钥由客户端生成,然后客户端利用服务器的公钥(从证书中提取)将共享密钥加密并将其发送到服务器。

TLS中提供的另一种密钥交换形式是基于另一种形式的公钥密码技术,由Diffie和Hellman于1976年发明,即所谓的Diffie-Hellman密钥交换。在Diffie-Hellman中,客户端和服务器都从创建DH参数对开始。然后,他们将其DH参数的公共部分发送给另一方。当双方都收到对方方的公共参数时,它们将它与自己的私钥组合在一起,最终计算出同一个值:前主密钥。然后,服务器使用数字签名来确保交换未被篡改。如果客户端和服务器都为每次密钥交换选择一个新的DH参数,则该密钥交换称为“Ephemeral”(DHE)。

两种模式都会使客户端和服务器具有共享密钥,但RSA模式有一个严重的缺点:它不是前向保密的。这意味着如果有人记录加密的对话,然后获得了服务器的RSA私钥,他们就可以解密对话。这甚至适用于记录对话,在之后的一段时间内获取私钥的情况。如果一个国家政府正在记录这些加密内容,然后使用Heartbleed这样的漏洞来窃取用户私钥,这将是一个非常现实而且非常恐怖的事情。

RSA密钥交换在一段时间内一直存在问题,其原因不仅仅是因为它支持前向保密。而是因为想要正确的实现RSA密钥交换也是不容易的。1998年,Daniel Bleichenbacher在SSL中使用RSA加密时发现了一个漏洞并创建了所谓的“百万消息攻击”, 它允许攻击者通过发送数百万条消息或一些特定的消息给服务器,根据服务器响应的不同错误码计算加密密钥, 进而解密消息。多年来,这种攻击得到了改进,在某些情况下只需要数千次就可破解,这使得在笔记本电脑上都可以破解。最近发现,许多大型网站(包括facebook.com)在2017年也受到Bleichenbacher变种漏洞的影响,即ROBOT攻击

为了降低非前向加密连接和Bleichenbacher漏洞所带来的风险,RSA加密已从TLS 1.3中删除,将Diffie-Hellman Ephemeral作为唯一的密钥交换机制。在下面的性能部分中我们将讨论删除RSA密钥交换带来的其他优势。

以Diffie-Hellman命名的加密手段

在加密方面,提供太多选项反而会导致选择错误。在选择DH参数时,这个原理最为明显。在以前版本的TLS中,DH参数的选择取决于参与者。这导致在一些算法实现中参数选择不正确,导致最后部署易受攻击。于是TLS 1.3取消了这一选择。

DH是一个功能强大的工具,但并非所有DH参数都可以“安全”使用。DH的安全性取决于称为数学中离散对数问题的难度。如果可以解决一组参数的离散对数问题,就可以提取私钥并破坏协议的安全性。一般来说,使用的数字越大,解决离散对数问题就越困难。因此,如果您选择较小的DH参数,就有可能遭受攻击。

2015年的LogJam和WeakDH攻击表明,许多TLS服务器可能被欺骗使用较小的DH的参数,允许攻击者破坏协议并解密对话。

DH参数还需要具有某些其他数学属性。2016年,Antonio Sanso 在OpenSSL中发现了一个漏洞,该漏洞正是由于选择的参数缺乏正确的数学属性导致的。

TLS 1.3采用固定路由,将DH参数限制为已知安全的参数。但仍然保留了个选择,如果只允许一个选择,一旦以后发现这些参数不安全的,更新TLS将变得很困难。

修复密码

混合加密方案的另外一部分是数据加密。数据加密主要通过一个对称算法以及双方协商出的会话密钥来完成的。下面我将告诉你,即时有很多算法可以完成数据的加密,但很多是不正确的。

CBC模式密码

在上一节中,我们将TLS描述为混合加密方案,具有公钥和对称密钥两部分。公钥部分并不是多年来造成麻烦的唯一部分。对称加密部分也存在安全问题。在任何安全通信方案中,您都需要保证数据加密和数据的完整性(以确保人们不会修改,添加或删除对话内容)。对称密钥加密数据可用于提供数据的加密和数据的完整性,但在TLS 1.2及更早版本中,这两个部分以错误的方式组合,导致安全漏洞。

执行对称加密和解密的算法称为对称密码。对称密码通常有两种主要形式:分组密码和流密码。

流密码采用固定大小的密钥并使用它来创建任意长度的伪随机数据流,称为密钥流。要使用流密码进行加密,需要将密钥流的每个位与消息的相应位进行异或。要解密,需要使用密钥流对加密消息进行异或。纯流密码示例如RC4和ChaCha20。流密码很受欢迎,因为它们易于实现且计算速度快。

分组密码与流密码不同,因为它只加密固定大小的消息。如果要加密比块大小更短或更长的消息,则必须执行一些额外操作。对于较短的消息,必须在消息的末尾添加一些额外的数据。对于较长的消息,可以将消息拆分为密码可以加密的块,然后使用分组密码模式将各个部分以某种方式组合在一起。或者,可以通过使用块密码加密计数器序列将快密码装换成流密码。这称为“计数器模式”。使用分组密码加密任意长度数据的一种流行模式称为密码块链接(CBC)模式。

为了防止人们篡改数据,加密是不够的,还需要保护数据的完整性。对于CBC模式密码,这是使用消息验证代码(MAC)来完成的。密码强度高的MAC具有以下特性:除非你知道密钥,否则找到与输入匹配的MAC值几乎是不可能的。有两种方法可以组合MAC和CBC模式密码。先加密,然后MAC密文,或者首先MAC明文,然后加密整个文件。在TLS中,他们选择后者,MAC-then-Encrypt,结果证明是错误的选择。

你可以理解为这个选择导致了BEAST漏洞,以及一系列填充oracle漏洞,例如Lucky 13Lucky Microseconds。阅读我之前关于这个主题的帖子,这里有全面的解释。CBC模式与填充之间的相互影响也是导致SSLv3或一些TLS中广泛流传的POODLE漏洞的原因。

RC4是Ron Rivest(RSA的“R”)设计的经典流密码,自TLS早期就获得广泛支持。在2013年,它被发现具有可衡量的偏差,攻击者可以利用它来解密消息。

AEAD模式

AEAD模式

在TLS 1.3中,已删除所有有威胁的密码和密码模式。您不能再使用CBC模式密码或不安全的流密码,如RC4。TLS 1.3中允许的唯一类型的对称加密是一种称为AEAD(带有附加数据的经过身份验证的加密)的新结构,它将数据加密以及数据的完整性无缝结合。

修复数字签名

TLS的另一个重要作用是身份验证。在每个连接中,服务器使用具有公钥的数字证书向客户端验证自身。在RSA加密模式中,服务器通过解密预主密钥以及会话中MAC值的验证来证明其对私钥的所有权。在DH模式中,服务器使用数字签名证明私钥的所有权。如果你到目前为止一直关注这篇博文,应该很容易猜到这是有问题的。

PKCS#1v1.5

Daniel Bleichenbacher致力于识别TLS中RSA的问题。2006年,他设计了针对TLS中使用的RSA签名的pen-and-paper攻击。后来发现包括NSS和OpenSSL在内的主要TLS实现容易受到这种攻击。这些漏洞也与是否正确实现填充有关。前面的这些情况中,RSA签名所用的都是PKCS#1 v1.5填充。在TLS 1.3中,删除了对PKCS#1 v1.5的支持,应用了更新的设计RSA-PSS

签名整个握手记录

我们之前描述过服务器如何使用数字签名来证明密钥交换没有被篡改。在TLS 1.2及更早版本中,服务器的签名仅涵盖部分握手。握手的其他部分,特别是用于协商使用哪个对称密码的部分,不由私钥签名,而使用的是对称MAC来确保握手未被篡改。这种疏忽导致了许多备受瞩目的漏洞(FREAK,LogJam等)。在TLS 1.3中,阻止了这样的做法,因为服务器签名了整个握手记录。

FREAK,LogJam和CurveSwap漏洞利用了两件事:

  1. 许多浏览器和服务器仍然支持20世纪90年代出现的弱密码(称为导出密码);
  2. 用于协商使用哪种密码的握手部分未经数字签名。

中间人攻击者可以通过让客户端选择服务器端支持的弱密码(或支持的组或支持的曲线)进行密钥交换。然后他们破解了该密钥,完成两条finish messages,让双方都认为他们已经同意通信。

这些攻击被称为降级攻击,它们允许攻击者强制两个参与者使用双方支持的最弱密码,即使支持更安全的密码也是如此。在这种攻击方式中,劫持者处于握手的中间,并将从客户端发送给的服务器支持的密码列表更改为仅包含弱导出密码。然后,服务器选择一个弱密码,攻击者通过暴力攻击计算出密钥,允许攻击者在握手时伪造MAC。在TLS 1.3中,这种类型的降级攻击是不可能的,因为服务器现在签名了整个握手,包括密码协商部分。

通过简化改善生活

随着除去了上面这些不安全的因素, TLS 1.3 是一个更加优雅和安全的协议。这种改变允许简化协议,使其更容易理解,更快。

没有更多的外卖菜单

在以前版本的TLS中,主要的协商机制是密码组。密码套件几乎涵盖了可以就连接进行协商的所有内容:

  • 支持的证书类型
  • 用于导出键的哈希函数(例如,SHA1,SHA256,…)
  • MAC功能(例如,HMAC与SHA1,SHA256,…)
  • 密钥交换算法(例如,RSA,ECDHE,……)
  • 密码(例如,AES,RC4,……)
  • 密码模式,如果适用(例如,CBC)

先前版本的TLS中的密码套已经发展成为巨大的字母组。常用密码套件的示例是:DHE-RC4-MD5或ECDHE-ECDSA-AES-GCM-SHA256。每个密码套件由一个名为Internet Assigned Numbers Authority(IANA)的组织维护的表中的代码点表示。每次引入新密码时,都需要将一组新的组合添加到列表中。这导致代码点的组合爆炸,代表这些参数的每个有效选择。它变得有点乱。

TLS 1.3删除了许多这些遗留功能,允许在三个正交协商之间进行彻底拆分:

  • 密码+ HKDF哈希
  • 密钥交换
  • 签名算法

这种简化的密码套件协商和从根本上减少的一系列协商参开辟了一种新的可能性。这种可能性使得TLS 1.3握手延迟从两次往返降至仅一次往返,从而提供性能提升,确保TLS 1.3受欢迎并广泛采用。

性能

在TLS1.2中,初次建立连接时,需要两次往返才能开始发送数据。这与服务器和客户端在地理位置上彼此是否靠近没有特别明显关系,但是它在移动网络上却有很大的差异,其中延迟可以高达200ms,这对于人类来说是显而易见的。

1-RTT模型

TLS 1.3现在具有更简单的密码协商模型和简化的密钥协商选项(没有RSA,没有用户定义的DH参数)。这意味着每个连接都将使用基于DH的密钥协议,并且服务器支持的参数很容易猜到(ECDHE使用X25519或P-256)正因为这种有限的选择,客户端可以很容易的选择在第一条消息中就发送DH密钥共享参数,而不是等到服务器确认它支持哪些密钥共享。这样,服务器可以获得共享密钥并减少一次往返,提前发送加密数据。例如,Chrome实现的TLS 1.3会在第一条消息中向服务器发送X25519密钥共享。

在极少数情况下,服务器不支持客户端发送的密钥共享之一,服务器可以发送HelloRetryRequest消息,让客户端知道它支持哪些密钥共享算法。由于列表已被削减太多,预计这种情况不常发生。

0-RTT恢复

受[QUIC协议的启发,协议得到进一步的优化。它允许客户端将第一条消息中的数据加密后发送到服务器,而且与未加密的HTTP相比,不会产生额外的延迟成本。这是一个重大的改进,一旦TLS 1.3被广泛部署,加密的网络肯定比以前更加快捷。

在TLS 1.2中,有两种方法可以恢复连接,会话ID和会话票据。在TLS 1.3中,将这些模式组合起来,形成了预共享密钥(PSK)恢复的新模式。该想法来源于,在建立会话之后,客户端和服务器可以导出称为“恢复主密钥”的共享秘密。该共享秘密可以使用id(会话ID样式)存储在服务器上,也可以通过服务器的密钥(会话票据样式)加密。此会话票据将发送到客户端并在恢复连接时发回。

对于恢复的连接,双方共享恢复主密钥,因此除了提供前向保密之外,不需要密钥交换。下次客户端连接到服务器时,它可以从上一个会话中获取密码并使用它来加密应用程序数据以及会话票证发送到服务器。

可重复性

0-RTT中没有数据交互。它由客户端发送,并由服务器使用,没有任何交互。这对性能很有帮助,但为此也需要付出代价:可重复性。如果攻击者捕获发送到服务器的0-RTT数据包,他们可以重播它,并且服务器有可能认为它是有效。这会产生一些有意思的负面影响。

危险重放数据的一个演示就是更改服务器数据的状态。如果将增加计数器,执行数据库事务或执行任何具有永久效果的操作放入0-RTT数据中是有风险的。

作为客户端,您可以尝试通过仅将“安全”请求放入0-RTT数据来防止这种情况。这里的“安全”表示请求不会更改服务器状态。在HTTP中,不同的方法应该具有不同的语义。HTTP GET请求应该是安全的,因此浏览器通常通过在0-RTT中只发送GET请求来保护HTTPS服务器免受重放攻击。由于大多数页面加载以GET“/”开头,因此页面加载时间更快。

当在0-RTT中发送的数据用于状态改变请求时,就会发生问题。为帮助防止这种问题,TLS 1.3还包括会话票据中的时间戳。如果这种情况发生太大分歧,客户要么接近光速,要么重放数据。在任何一种情况下,服务器都应该谨慎拒绝0-RTT数据。

有关0-RTT的更多详细信息以及TLS 1.3中会话恢复的改进,请查看此前的博客文章

可部署性

TLS 1.3与TLS 1.2及更早版本完全不同,但为了广泛部署,它必须向后兼容现有软件。TLS 1.3从草案到最终发布花了这么长时间的原因之一是,一些现有的软件(即中间键)与新的更改并没有很好地协调。即使在线上对TLS 1.3协议进行一些微小更改(例如消除冗余的ChangeCipherSpec消息,将版本从0x0303提升到0x0304)都会导致某些人的连接问题。

尽管未来的灵活性已经内置到TLS规范中,但是一些实现对如何处理未来的TLS版本做出了错误的假设。造成这种变化的现象称为骨化,我在前一篇文章中更全面地探讨了TLS 1.3尚未部署的原因。为了适应这些变化,TLS 1.3被修改为看起来很像TLS 1.2会话恢复(至少在线路上)。这导致了虽然增加了更多功能但不太美观。这是您在线升级最广泛部署的协议之一所付出的代价。

总结

TLS 1.3是一种现代安全协议,使用正式 分析等现代工具构建,保持其向后兼容性。它已经过广泛测试,并在使用现实部署数据时进行了迭代。它是一种更清晰,更快速,更安全的协议。所有Cloudflare客户默认启用TLS 1.3 。

发布TLS 1.3是一项巨大的成就。这是最近最好的一个示例,如何使用已部署长达20年的遗留代码并动态更改它,从而为每个人提供更好的互联网。TLS 1.3在过去三年中一直在争论和分析,现在已准备好迎接黄金时段。欢迎,RFC 8446。