过去5年来,国际互联网工程任务组(IETF)一直致力于标准化传输层安全协议(TLS)的最新版本,这个协议是任务组旗下最重要的安全协议之一,而IETF是定义互联网协议的标准机构。TLS用于保护web(还有更多!),提供加密并确保每个HTTPS网站和API的真实性。TLS的最新版本TLS 1.3 ( RFC 8446 )今天发布。这是该协议的首次重大修订,带来了重大的安全和性能改进。本文将深入探讨TLS 1.3中引入的更改及其对internet安全的未来的影响。

An evolution

Cloudflare所提供安全性的一个主要方式是在网站和API等Web服务上支持HTTPS。使用HTTPS(“S”代表安全的),你的浏览器和服务器之间的通信将通过加密和经过身份验证的通道传输。 通过HTTPS而不是HTTP提供内容可以让访问者确信他们所看到的内容是由合法内容所有者给出的,并且通信是安全的,不会被窃听。在这个世界里,在线隐私比以往任何时候都更加重要,这确实是一件大事情。

使HTTPS安全的后台机制是一种称为TLS的协议。它源于九十年代中期在Netscape上开发的称为安全套接字层(SSL)的协议。 到20世纪90年代末,Netscape将SSL移交给IETF,IETF将其重命名为TLS,并从此成为该协议的管理者。许多人仍将Web加密称作SSL,即使绝大多数服务已切换到仅支持TLS。SSL这个术语继续受到人们的欢迎,而Cloudflare通过 Keyless SSL Universal 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穿着降落伞裤和垫肩

在过去的几年里,TLS遇到了很多问题。首先,实现TLS协议的项目代码问题蛮多,包括 Heartbleed BERserk goto fail 等。这些问题大部分不能归因于协议的逻辑基础,往往由于项目本身缺乏测试。 TLS Attacker Project Wycheproof 等工具帮助提高了TLS实现的健壮性,但TLS面临的更具挑战性的问题必须靠协议本身来解决。

TLS是由工程师使用数学工具设计出来的。很多SSL时代的早期的设计决策都基于启发式方法,而且在不完全理解如何设计健壮的安全协议的情况下。也就是说,这不是协议设计者的错(Paul Kocher, Phil Karlton, Alan Freier, Tim Dierks, Christopher Allen 等人),由于整个行业都还在学习如何正确地做到这一点。在设计TLS的时候,关于如何设计安全身份验证协议的正式论文,如Hugo Krawczyk 的里程碑式的 SIGMA 论文的出现,还是许多年后的事了。TLS是90年代的加密技术:在当时它是很出色的,而且看起来很酷,但是现代加密技术的设计风格已经发生了变化。

很多设计缺陷都是使用形式验证( formal verification )发现的。学者们尝试证明TLS的完全安全特性,反而却发现了一些反例,变成了真正的漏洞。这些缺陷遍布了纯理论的漏洞( SLOTH CurveSwap ),到资源丰富的攻击者的可行漏洞( WeakDH , LogJam , FREAK , SWEET32 ),再到可实现的重大危险漏洞( POODLE , ROBOT )。

TLS1.2有点慢

加密在网络上一直都很重要,但是历史上它仅用于像登录或者发送信用卡信息之类的数据,而大多数其他数据都是明文暴露的。近年来,对网络上所有的通信都使用HTTPS已经成为了主流趋势。这对保护我们在网络上更多的数据避免窃听和 注入攻击 有积极影响,但是缺点就是这种新连接有点慢。

为了让浏览器和web服务器协商秘钥,他们需要交换密码数据。这个交换,在TLS中称为“握手”,这个过程从1999年TLS标准化以来一直保持不变。在加密数据发送之前(或者重新开始之前的连接的时候),握手在浏览器和服务器之间需要两次额外的往返交互。与单独使用HTTP通信相比,HTTPS中的TLS握手产生的额外代价会对延迟产生明显的影响。这种额外的延迟会对以性能为主的应用产生负面影响。

定义TLS1.3

由于对TLS 1.2过时设计和经常性的两次往返开销的不满,IETF开始定义一个TLS的新版本。在2013年8月,Eric Rescorla 为新协议列出了一个特性愿望清单: https://www.ietf.org/proceedings/87/slides/slides-87-tls-5.pdf

经过 一些讨论 ,决定这个TLS的新版本称为TLS 1.3。驱使TLS 1.3的设计的主要问题与5年前的基本相同:

  • 减少握手等待时间

  • 加密更多的握手

  • 改善跨协议攻击的弹性

  • 删除遗留特性

该规范是由志愿者通过开放式设计过程形成的,经过4年的辛勤工作和激烈的辩论,已经形成了TLS 1.3的最终格式:RFC 8446。随着越来越多的使用,新协议将使互联网更快、更安全。

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

修枝剪叶

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

固定秘钥交换

TLS是一种所谓的“混合式”加密系统。也就是说它既使用了对称秘钥加密(加解密的秘钥相同),还使用了公钥秘钥加密(加解密秘钥不同)。混合体系是在互联网上加密的主要形式,用于 SSH , IPsec , Signal , WireGuard 和其他协议。在混合加密系统中,公钥加密用于在两端之间建立一个共享秘钥,然后使用共享秘钥创建对称秘钥,然后它就可以用于加密交换的数据。

一般来说,公钥加密不仅慢开销还大(每个操作微秒到毫秒级),而对称秘钥加密快且开销小(每个操作纳秒级)。由于混合加密体系对开销大的操作只做一次,因此它可以让你在极小的开销下发送大量加密数据。在TLS 1.3中大量工作都是关于改善握手部分,而使用公钥建立对称秘钥就处于这个阶段。

RSA秘钥交换

TLS的公钥部分的作用就是建立一个共享秘钥。通过公钥有两种主要方式可以达成这个目的。简单点的方法是使用公钥加密:一方使用另一方的公钥加密共享秘钥然后直接将其发送出去。然后另一方使用它的私钥解出共享秘钥然后…瞧!他们都有了相同的秘钥。这个技术是Rivest,Shamir和Adelman在1977年发现的,因此称其为RSA秘钥交换。在TLS的RSA秘钥交换中,共享秘钥由客户端来决定,然后将其使用服务端的公钥(从证书导出的)加密,然后发送给服务器。


TLS中使用的其他秘钥交换的形式是基于另一种公钥加密的形式,它是由Diffie和Hellman在1976年发明的,因此成为Diffie-Hellman秘钥协议。在Diffie-Hellman协议中,客户端和服务器都会创建一个公私钥对,由此作为开始。然后他们将公钥部分发送给另一方。当每一方都收到了对方的公钥,他们使用各自的私钥将其组合,并以相同的值作为结尾:即 pre-master secret。然后服务器使用数字签名来保证交换的数据没有被篡改。如果客户端和服务器在每一个数据交互中都选择一个新的秘钥对,这种秘钥交换则称为“临时秘钥(ephemeral)”。

这两种模式都可以让客户端和服务器得到共享秘钥,但是RSA模式有一个严重的缺陷:它不满足 前向保密(forward secret) 。意思是如果有人记录了加密对话,然后获取服务器的RSA私钥,他们可以将对话解密。甚至如果对话先被记录下来,而秘钥在未来的某个时候才获得,这种方法仍然有用。有这样一种情况,各国政府都在记录加密过的对话,然后使用一些比如 心脏出血(Heartbleed) 之类的技术来偷取私钥,这确实是一个切实可行的威胁。

RSA秘钥交换存在问题了有一段时间,这不仅仅因为它不是前向保密的。它还出了名的容易出错。在1998年,Daniel Bleichenbacher发现了在SSL中使用RSA加密容易受到攻击,而且创造了所谓的“百万消息攻击”,即攻击者通过发送一百万条左右的精心设计的消息,来让服务器使用私钥执行RSA私钥操作,然后查找返回的错误代码的不同。这些年来攻击已经被重新定义了,在一些情况下只需请求数千次消息,这在一台笔记本电脑上都可以做到。最近人们发现,一些大网站(包括facebok.com)也很容易受到Bleichenbacher 攻击的变体的攻击,即 ROBOT攻击 ,这种攻击最早出现在2017年。

为了减少由非前向保密连接和百万消息攻击引发的风险,TLS1.3已经移除了RSA加密,保留了临时Diffie-Hellman作为唯一的秘钥交换机制。移除RSA秘钥交换也带来了其他的好处,我们将在下面的性能章节来讨论它。

Diffie-Hellman组命名

当涉及到密码学时,提供太多的选项会导致选择错误的选项。当选择Diffie-Hellman参数时,这一规则最为明显。在TLS早期版本,Diffie-Hellman参数的选择取决于人。这导致了由于一些实现选择错了,从而导致部署了容易被攻击的实现。TLS 1.3取消了这个选项。

Diffie-Hellman是一个强大的工具,但是不是所有的Diffie-Hellman参数用起来都是安全的。Diffie-Hellman的安全取决于特定的数学问题,即 离散对数问题(discrete logarithm problem) 。如果你能破解一组参数的离散对数问题,你就能提取出私钥,从而打破这个协议的安全性。一般来说,使用的数越大,其离散对数问题越难以破解。因此如果你选择了小的DH参数,你就麻烦了。

2015年的LogJam和WeakDH攻击表明,许多TLS服务器可以被骗为Diffie-Hellman使用小数字,从而允许攻击者破坏协议的安全性并解密会话。

Diffie-Hellman还要求参数具有某些其他数学特性。2016年,Antonio Sanso在 OpenSSL中发现了一个问题 ,即选择的参数缺少正确的数学属性,从而导致另一个漏洞。

TLS 1.3采取了固执己见的路线,将Diffie-Hellman参数限制在已知安全的参数范围内。然而,它仍然有几个选择;如果只允许一个选项,那么在将来某个时候发现这些参数不安全时,就很难更新TLS。

修改密码

混合加密方案的另一半是实际的数据加密。这是通过将身份验证代码和对称密码结合起来实现的,双方都知道密钥。正如我将要描述的,有许多加密数据的方法,其中大多数都是错误的。

CBC模式密码

在上一节中,我们将TLS描述为一种混合加密方案,包含一个公钥部分和一个对称密钥部分。公钥部分并不是多年来唯一引起麻烦的部分。对称的关键部分也有自己的问题。在任何安全通信模式中,您都需要加密(以保持信息的私密性)和完整性(以确保人们不会修改、添加或删除对话片段)。对称密钥加密用于提供加密和完整性,但在TLS 1.2和更早的版本中,这两部分以错误的方式组合,导致安全漏洞。
执行对称加密和解密的算法称为对称密码。对称密码通常有两种主要形式:分组密码和流密码。

流式密码采用固定大小的密钥并使用它来创建任意长度的伪随机数据流,称为密钥流。使用流式密码进行加密时,你可以通过将密钥流的每个位与消息的相应位进行异或来获取消息并将其与密钥流合并。解密时,你须获得加密后的消息并使用密钥流对其进行异或处理。纯流式密码的示例是RC4和ChaCha20。流式密码很受欢迎,因为它们在软件上易于实现且运行速度快。

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

为了防止人们篡改数据,加密是不够的。数据还需要受到完整性保护。对于 CBC 模式加密,这是通过使用称为消息验证码(message-authentication code,MAC)的东西来完成的,这类似于带有密钥的校验和。密码强的 MAC 具有以下特性:除非你知道密钥,否则找到与输入匹配的 MAC 值几乎是不可能的。有两种方法可以整合 MAC 和 CBC 模式加密。你可先加密,然后用 MAC 加密生成的密文,或者首先 MAC 加密明文,然后加密其输出文件。在 TLS 中,他们选择后者,MAC-then-Encrypt,事实证明这是一个错误的选择。

你可以将这个选择归咎于 BEAST ,以及一系列填充 oracle 漏洞,例如 Lucky 13 Lucky Microseconds 。阅读我之前关于这个主题的 博文 ,以全面了解这些缺陷。CBC 模式和填充之间的交互也是 SSLv3 和一些 TLS 实现中广泛宣传的 POODLE 漏洞原因。


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


AEAD 模式

在 TLS 1.3 中,已移除所有麻烦的密码和密码模式。你不能再使用 CBC 模式密码或不安全的流式密码,如 RC4 。 TLS 1.3 中允许的唯一类型的对称加密是一种称为 AEAD authenticated encryption with additional data )的新结构,它将加密性和完整性整合到一个无缝操作中。

修复数字签名

TLS的另一个重要部分是身份认证。在每个连接中,服务器使用具有公钥的数字证书向客户端验证身份。在RSA加密模式中,服务器通过解密pre-master密钥并在会话的记录上计算MAC来证明其对私钥的所有权。 在Diffie-Hellman模式下,服务器使用数字签名证明私钥的所有权。如果你到目前为止一直关注这篇博文,应该很容易猜到这么做也是错误的。

PKCS#1v1.5

Daniel Bleichenbacher长期致力于识别TLS中RSA的问题。在2006年,他设计了针对TLS中使用的RSA签名的笔纸攻击。后来发现包括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. 用于协商使用哪种密码的握手部分未经数字签名。

“中间人”攻击者可以通过服务器支持的易于破解的选择从客户端得到所支持的密码(或支持的群组或支持的曲线)。之后他们会打破其关键并伪造了两条已完成的消息,让双方都认为他们已经同意了传输协议。

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

精简带来更好的状态

移除了上面列出的不安全特性后,TLS 1.3协议变得更加优雅和安全的。协议经过这种像树篱般剪除枝丫后的精修后,理解协议变得更容易和更快。

没有更多的外带菜单

在之前的TLS版本中,主要的协商机制是密文套件。一个密文套件包含了几乎所有可以协商的连接:

  • 支持类型的证书

  • 用于派生键的哈希函数(例如SHA1, SHA256,…)

  • MAC功能(例如:HMAC with SHA1, SHA256,…)

  • 密钥交换算法(如RSA, ECDHE,…)

  • 密码(例如,AES, RC4,…)

  • 密码模式(如适用)(如CBC)

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

TLS 1.2

TLS 1.3

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

  • Ciper + HKDF Hash

  • 密钥交换

  • 签名算法

这种简化的cipher suite协议并从根本上减少的协议参数集之后开辟了一种新的可能性。这种可能性使得TLS 1.3握手延迟从两次往返降至仅一次往返,从而提供可确保TLS 1.3流行并被广泛采用的性能提升。

性能

建立与之前没有见过的服务器的新连接时,需要两次往返才能在连接上发送数据。这在处于地理位置上彼此靠近的服务器和客户端上并不是特别明显,但它可以在移动网络上产生很大的差异,其中延迟可以高达200ms,这对于人来说是显而易见的。

1-RTT模式

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

在极少数情况下,服务器不支持客户端所发送的某一密钥共享,服务器可以发送一个新消息HelloRetryRequest,让客户端知道它支持哪些组。由于列表已被缩减太多,估计类似情况不常发生。

0-RTT恢复

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

在TLS 1.2中,有两种方法可以用于恢复连接,会话 id和会话ticket 。在TLS 1.3中,这些被组合起来以形成称为PSK(pre-shared key,预共享密钥)恢复的新模式。其思路是在建立会话之后,客户端和服务器可以得到称为“恢复主密钥”的共享密钥。这可以使用id(会话ID样式)存储在服务器上,也可以通过仅为服务器所知的密钥(会话ticket样式)进行加密。此会话ticket将发送到客户端并在恢复连接时进行查兑。

对于已恢复的连接,双方共享恢复主密钥,因此除了提供前向保密之外,不需要交换密钥。下次客户端连接到服务器时,它可以从上一个会话中获取秘密并使用它来加密应用程序数据以及会话ticket发送到服务器。像第一次飞行中发送加密数据一样惊人的事情确实伴随着它的衰落。

可重复性

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是一种现代安全协议,使用 formal analysis 等现代工具构建,以保持其向后兼容性。它已经过广泛测试,并在使用现实世界中的已部署数据进行了迭代。它是一种更清晰、更快速、更安全的协议,可以在线上成为事实上的双方加密协议。对于所有 Cloudflare 客户,默认情况下启用TLS 1.3草案28,我们将很快推出最终版本。

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

本文地址: https://www.oschina.net/translate/rfc-8446-aka-tls-1-3

原文地址: https://blog.cloudflare.com/rfc-8446-aka-tls-1-3/