hi

无钥加密套接字协议层:技术细节追踪溯源

原文链接: blog.cloudflare.com

无钥SSL: 技术细节的追踪溯源

2014年9月19日 Nick Sullivan.

Tweet

CloudFlare's Keyless SSL

我们昨天宣布无钥SSL后,收到了排山倒海般积极的响应。我们从博客、RedditHacker News上通读了评论,人们看来对相关知识很有兴趣并希望了解更多更深入的技术细节。所以我们在这篇博文中特地细化了问题的答案:关于无钥SSL是怎样设计、怎么运行以及为何它是安全的。在我们做这些之前,我们需要有一些关于加密是如何工作的背景。如果你已经熟悉了,此处可忽略。

TLS

传输层安全(TLS)是web安全的重中之重。它让网站在web浏览器中证明了它们的身份,并使用数据加密技术保护了所有交换信息免受窥探。TLS协议已经存在了很多年,但是它仍然很神秘,哪怕是面对骨灰级的技术狂热者。而理解TLS的基本原理是理解无钥SSL的关键所在。

双重目标

TLS有两个主要目的:安全和权限。 两个对互联网的信息通信安全都很重要。

当两部分都是加密的,通讯就会被考虑是加密的,且没有人能知道他们的对话情况。当应用对称加密时就能达到加密的目的:在发送前用一个密钥了解到两部分已经参与了加密。在TLS中,这个对称加密算法是一个典型的使用了强分组密码的案例,例如AES(先进加密标准)。老版浏览器和平台可能会用一个类似Triple DES的密码或流密码RC4, 但现在认为这已经是不安全的了。

TLS另一个重要的目的就是认证。 认证是确保某角色在另一端告知他们是谁的方式。这可以由一个公钥完成。网站用证书和公钥密码在浏览器中去证明他们的身份。并且浏览器需要两个事情去信任一个证书:证明他们某一部分是证书的所有者,并证明证书是可信赖的。

一个网站证书包含一个公钥,且如果网站能证明他们能控制相关私钥, 那就可以证明他们是证书的所有者。如果证书被一个可信赖的证书认证授权过,那浏览器就会用到一个可信赖的证书,并且包含网站的域名。 更多关于我们的开源SSL工具 - CFSSL是如何配合一个web证书使用的技术细节,在前一篇博客中描述过。

在web的上下文,加密和认证是通过确定一个共享密钥来证明一个证书所有权。TLS通过一系列谓之“信号交换”(handshake)的消息来做到这个。

什么是信号交换?

Cheesy handshake stock photo

TLS协议是Netscape从90年代中期的安全套接层(SSL)协议进化而来。在1999年,网络工程Task Force(IETF)制订了一个被称为TLS的新协议,一个SSL的升级版本。实际上,TLS和SSL如此之像以至于TLS1.0用的其实是SSL协议的3.1版本。这个一开始会有点迷惑人,但只把TLS当做SSL3.0一个非主要版本的升级就显得合理了。TLS之后的版本只是跟随这个升级。TLS还未革命SSL协议之前,人们还是习惯交替使用TLS和SSL。

在TLS中主要有两类信号交换:一个基于 RSA),另一个基于Diffie-Hellman。RSA和Diffie-Hellman(密钥交换系统概述)是现代密码学的两种具有领导力的算法,并把密码学带给了大众。这两种信号交换仅在怎样实现密钥建立和认证时才有所差别:

alt

RSA和DH信号交换都有他们自己的优缺点。RSA仅用一个公钥算法操作。一个DH和RSA认证信号交换需要相同的RSA操作, 但要带一个额外的DH操作。RSA会给出认证,且RSA信号交换时能更快的去运算。像RSA和DH这样的公钥算法会占用很多CPU,并且是TLS信号交换中最慢的部分。相比每秒10万次的对称加密算法AES,一个手提电脑仅能每秒执行几百次RSA加密运算。

DH信号交换需要两种算法运行,但是这个优势仅允许密钥的制定是独立于服务端的私钥的。这有个给出的内容链接正向加密,事实上如果私钥被暴露,一个有用的属性会保护被解码的会话。DH信号交换的版本也会有开启使用非RSA认证的可能性以便能改善性能, 包括椭圆曲线数字签名密钥。椭圆曲线能花费更少的计算开销却带来相同的安全性。一个DH信号交换和椭圆曲线DSA认证以及椭圆曲线的赫尔曼密钥协议能比单操作的RSA信号交换更快。

CloudFlare(美国云火炬)两种信号交换都支持,但是,如我们之后所描述,使用哪种信号交换类型是由server来选定的。无论何时CloudFlare都会选择一个DH信号交换。

TLS术语

在我们纵览信号交换的步骤之前,这里还有很多的术语。

1. 会话密钥(Session key) 这是一个信号交换的终端结果。 它是一个对称加密算法的密钥,这个密钥允许客户端和服务器互相加密信息。

2. 客户端随机(Client random) 这是一个客户端创建的32位序列号。 它对每一个连接来说都是唯一的, 并且在28位的随机字节数之后加了一个四位的时间戳。近来,谷歌Chrome切换使用了32位的客户端随机为了防止客户端的浏览痕迹被跟踪。这些随机值通常被称为nonce

3. 服务端随机(Server random) 服务端随机除了是在服务端生成随机外,跟客户端随机一样。

4. 预备主密码(Pre-master secret) 这是一个48位的数据块。它能合并客户端和服务端随机,并且用伪随机函数(“pseudorandom function” (PRF))在服务端随机去创建一个会话密钥。

5. 密码组(Cipher suite) 这是一个在TLS连接中为合并算法的唯一的身份。它为下列每一个特性定义了唯一算法。

  • 密钥建立 (typically a Diffie-Hellman variant or RSA)

  • 认证 (the certificate type)

  • 机密性 (a symmetric cipher)

  • 完整性 (a hash function)

举例“AES128-SHA”定义一个会话用于:

更棘手的,“ECDHE-ECDSA-AES256-GCM-SHA384” 定义了一个对话用于合法的加密组合:

让我们一起随着这些已定义的概念,一起纵览RSA信号交换吧。

RSA信号交换

注意:在带着一个会话密钥的、被加密的信号交换中是没有消息的;他们都被明码的方式发送了。

SSL 信号交换 RSA

信息 1: “客户端问候”

客户端问候包含客户端需要用的协议版本,以及一些其它取得初始信号交换的、包括客户端随机和密码组列表的信息。现代浏览器也包括他们查找的主机名,名为服务器名称指示 (SNI).SNI可以让web服务器主机在一个相同的IP地址上绑定多重域名。

信息 2: “服务端问候”

在接受了客户端问候之后,服务端获得了可以继续信号交换的参数。这个密码组的选择决定了什么类型的信号交换会被执行。服务端“问候”信息包含服务端随机、服务端被选择的密码组以及服务端认证等。 这认证涵盖了服务端的公钥和域名。

注意:精选的美国云火炬CloudFlare的密码组已经被公开发布在我们的 Github page上。

信息 3: “客户端密钥交换”

在验证认证是可信并属于他们访问的网站之后,客户端会创建一个随机的预备主密码。这个密码通过了认证的公钥加密,并且发送至服务端。

在收到消息时,服务器用它的私钥解码预备主密码。现在两端都有了预备主密码, 并且在客户端和服务端都是随机的,它们能共同获得一个会话密钥,并交互一个短信息去指示下一个发送的被加密信息。

当客户端和服务端交换了“完成”信息时,信号交换算是正式完成了。实际的文本是带着会话密钥的被加密的书面语:“客户端完成”或“服务端完成”。随后在两端的通讯都是伴随会话密钥且是被加密的。

这种信号交换是简练优雅的,因为它只用一步就结合了密钥交换和认证。这种逻辑是,如果服务器能正确的获得会话密钥,接着他们必须有获得私钥的权限,并且因此能成为认证的所有者。

信号交换的缺点就是被保护的信息仅仅是私钥加密。假设一个第三方记录了信号交换和随后的通信,如果未来第三方获得登入私钥权限,他们会解码预主密钥并获得会话密钥。接着他们就可以解码整个信息。可以确定这是可行的,哪怕认证已经过期或者被取消。这导致我们去另一个信号交换的表单时就得能够提供机密性,即使私钥已被盗用。

短暂的赫尔曼(Diffie-Hellman)信号交换

Diffie-Hellman GIF

短暂的赫尔曼(Diffie-Hellman)信号交换是一个可选的TLS握手协议表单。它用了两种不同的机制:其一确定一个预备主密码, 其二是为了服务器认证。 密钥的特性依赖于赫尔曼密钥协议算法。

在赫尔曼中,两个部分带着不同的密钥交换信息去获得一个可分享的密钥。这个信号交换依赖于简单的事实就是指数是可交换的。明确点说, 它会取一个数做为a的乘方,并和b的乘方比较,如果和b的乘方取得相同的数字,则结果就做为a的乘方。

算法工作如下:

  • person a 有密钥 a,发送 ga 到 person b

  • person b 有密钥 b, 发送 gb 到 person a

  • person a 计算 (gb)a

  • person b 计算 (ga)b

  • person a 和 b 都以共享密钥 gab 结尾

这跟常规数字结合运行的并不好,因为gab会变得很大,并且已有有效的方法去取得一个数字的n次方根。然而, 我们能改变问题领域并使其生效。我们会计算一个大的素数和其取得的余数的结果相除,然后再进行取整。这个称之为求模运算。在求模运算中取得一个n次方根被称之为离散对数问题 且被公认为是一个难题。

另一个赫尔曼密钥协议的变化是其使用了椭圆曲线,ECDHE。关于椭圆曲线的更多信息,可参考我们去年出版的素数 。 一个共享的密钥被获取后,能够用在控制赫尔曼浮点数长度密钥协议算法上。

现在让我们来纵览一个DH信号交换:

Diffie-Hellman TLS握手协议

信息 1: “客户端问候”

就如在安全用例中一样,客户端问候包含协议版本、客户端随机、一个密码组列表、并且有可多选的SNI扩展。如果客户端请求了ECDHE, 他们则包括支持曲线的列表。如果这个被省略或不匹配,它则成为棘手的调试

信息 2: “服务端问候”

在收到客户端问候之后,服务器得到了继续往前进行信号交换的参数,包括为ECDHE的曲线。服务端“问候”信息包含服务端随机,服务端选择了密码组以及服务端证书。

RSA和Diffie Hellman握手随着一个新信息类型点的开始变得不同。

信息 3: “服务端密钥交换”

为了开始赫尔曼密钥交换,服务器需要获取一些开始的菜蔬并发送它们到客户端 --- 这就和我们上面提到的 ga 相符合了。 服务端也需要一个证明它已经控制了私钥的方法,到目前为止,服务端计算出了一个所有信息的数字信号。在这个信息中,赫尔曼参数和信号都被发送了。

信息 4: “客户端密钥交换”

在确认证书可信之后, 且属于他们试图访问的网站, 客户端就会验证服务端发来的数字信号。接着它们也发送客户端赫尔曼信号交换的另一半。(类似上面提到的ga)

在这点上,两端能从赫尔曼参数(类似上面提到的gab)计算出预备主密码。 随着预备主密码的设置客户端和服务端都已随机, 它们能获得相同的会话密钥。接着它们交换一个短信息去表明它们下一个被加密的信息。

正如在RSA握手中一样,当客户端和服务端交换“完成”信息时,这次握手算是正式完成了。随后任何在两部分的通信都被会话密钥加密了。

无钥化

昨天我们宣称了无钥SSL, CloudFlare的解决方案允许网站在不需放弃他们私钥保护的情况下去使用CloudFlare。

在信号交换的关系图之上有一点,就是私钥在握手中仅能被使用一次。这允许我们在地域上能拆分TLS握手协议, 当转移私钥操作到一个远程的密钥服务器时,会伴随着大多数发生在CloudFlare的前沿握手。这个私钥服务器能推进用户基础设施的使用, 给他们独占访问私钥的权限。

一旦信号通道被确定,RSA握手协议看起来是这样的:

Keyless SSL handshake with RSA

DH(Diffie-Hellman)看起来如下:

Keyless SSL handshake with Diffie-Hellman

用这种方式扩展TLS握手需要改变NGINX服务和OpenSSL,以使其同时在远程和无阻塞情况下进行私钥操作(所以当NGINX在等待密钥服务器时能持续维持其它请求)。当NGINX和OpenSSL同时改变时,在CloudFlare服务器和密码服务器之间的协议会由输入顺序和Matasano安全性进行检查。他们发现无钥SSL和预置SLL的安全性是相等的。无钥SSL已经从可证明和性能角度两方面被学术界的研究人员进行研究了。

密码服务器可以运行在Linux上(已有针对Red Hat/CentOS、Debian和Ubuntu及其他Linux系统的加载包),以及其他Unix系统(包括FreeBSD)、微软Windows服务器等。用户也能得到一个用C写的参考进阶, 以便他们能搭建自己的兼容密码服务器。

密码服务器很快会被硬件安全模块(HSM)代理及密钥管理方案(例如Venafi)整合,以便在用户的基础设施中提供给他们更多的密钥管理方法。

无钥SSL支持给相同的认证提供多密钥服务器。 密钥服务器是无状态的, 允许用户使用现成的硬件,并可以线性地控制密钥服务器的部署和通信量。当在DNS负载均衡中运行多密钥服务器时,用户的网站是就能保持高可用状态。

保护先知

Protecting the Oracle

为了让无钥SSL更安全,从CloudFlare边界到密码服务器的连接也得是安全的。密码服务器可以作为一个加密图形先知,且能被任何能联系到的人执行私钥操作。确定那个仅是CloudFlare能请求密钥服务器去执行操作,是无钥SSL安全性的关键所在。

我们用相互制约的、已认证的TLS保护从CloudFlare到密钥服务器的连接。首先,我们描述TLS握手仅仅是单向已认证的:客户端被服务端验证。在已认证的TLS,客户端和服务端都有证书和认证相互制约。密钥服务器认证CloudFlare和CloudFlae认证密钥服务器。

在无钥SSL中,密码服务器仅允许带有CloudFlare内部证书授权签名的客户端。我们在连接的两端使用自己认证授权的证书。 我们在证书是怎么被授权及使用X.509 扩展密钥用法选项上有严格的控制,以保证证书仅用于预定用途上。这就能在包含密钥服务器的那些通信过程中,禁止那些没有被CloudFlare授权的参与者。客户在CloudFlareIP空间也有添加防火墙规则的选项去限制外来连接。

此外, 我们对如下其中之一密码组进行取整操作:

  • ECDHE-ECDSA-AES256-GCM-SHA384

  • ECDHE-RSA-AES256-GCM-SHA384

在OpenSSL中这是两个允许的最强密码,并且保证在CloudFlare和密钥服务之间有着完美的前沿安全性。

其它安全考虑

密钥服务器本身能被修改并和硬件安全模块(HSM)一起工作,为那些想要从未被发现软件的缺陷(类似Heartbleed)中保护密钥服务器额外的硬件安全。

密钥服务器并不受制于类似Bleichenbacher提到的这种补充oracle的攻击,因为它会用到恒定大小的相应。只要这种基础工具密码库作用在密钥服务器就可以抵抗攻击,例如定时攻击这种侧信道攻击就会失效。参考我们在实践中使用的OpenSSL,对类似的攻击已经久经考验了。

性能优化

CloudFlare是为了使网站更快而设计的:连接同一网站用CloudFlare的时间会少于不用CloudFlare的。这也是无钥SSL的情况。用无钥SSL连接一个站点将会快于用一个被禁止的CloudFlare。人们会追查这是怎么做到的,获得那些无钥SSL需要一个额外的密钥服务器的连接。答案就在那些地理位置上。

CloudFlare的数据中心地理分布在全球20个国家并且在定位少于20毫秒的95%的互联网活跃用户中。这允许访问者用一个CloudFlare服务器通信时在网络上更接近它们。信息在访问者和CloudFlare服务器之间发送不必再传输那么远,所以连接延迟很小。这种临近效应就是CloudFlare加速网站的其中一种方式。

在如下的无钥SSL图表中,所有在CloudFlare和访问者之间的信息,都期望一个在短连接之上的传输。

Keyless SSL reduces handshake round trip latency

考虑到一个在旧金山的访问者想要通过TLS访问一个主机在伦敦的站点的场景。没有CloudFlare,从旧金山到伦敦的TLS握手需要两个来回。 而随着无钥SSL和一个在伦敦的密码服务主机,访问者在CloudFlare中的访问将终结于就近的 San Jose数据中心。在这种场景下,仅有一个信息必须传输到伦敦再回来。信息必须传输一个更短的距离,且会导致一个更快的握手。

理由就是我们仅需要一个来回到密钥服务器去持久化住连接。一旦CloudFlare连接到了一个密钥服务器,它会保持住连接为任何访问此站点新访问者准备。第一个连接到无钥SSL站点是迅速的,但是主性能会随着一个访问者返回到此站点而有所提升。

简略信号交换

TLS提供一个被称之为“会话重置”的优秀的性能特性。如果一个用户在服务器上有一个被预先判定的会话,并且试图再次连接,它们则会用一个简化握手过程。这里有两种机制:会话ID和会话票据。

会话ID需要服务器去做一个准备工作:保持会话状态(例如:会话密钥),以防一个预备会话被重置。 至于会话票据,服务器会在握手初始化期间发送一个会话票据(由会话密钥和一个标签密钥加密组成)到客户端。 当会话被重置,客户端发送加密密钥返回到一个已解密这个密钥并重置了会话的服务器端。这里的会话重置不需要去用私钥。

火狐和chrome是支持会话票据的主要浏览器。其他现代浏览器都是通过会话ID来支持会话重置的。当使用这些技术到一定规模时,所要面临的挑战之一就是负载均衡。为了重置服务器的一个连接,它需要有被预判的会话密钥。如果访问者试图用一个新服务器重置连接,则那个服务器需要以某种方式获得原始的会话密钥。

这个会话重置的主要问题不意味着去控制被负载均衡的服务器。如果一个客户端在一个服务端上开始一个会话,它就不能在另一个台服务器上重置会话。这并不是协议的一次衰败,只是在开源web服务器上的缺失特征。

随着无钥SSL问题的深入,我们介绍了高级的会话重置能够去解决这个问题。这包含在世界范围内数据中心通过会话ID的会话重置和通过会话票据的会话重置。会话重置允许闪电般快速重复的连接访问多次,因为那里不再需要返回到无钥服务器去重置一个连接。

会话票据恢复

就会话票据而言,我们能从我们网络上的任何机器上重置一个会话。如果我们把它开放给社区的话,这需要很大的工程量。

Session resumption with session tickets

Twitter的最新发布使用了每隔12小时轮询的会话票据密钥。我们在每个小时会话票据的轮询中都会加码,并构建了一个中心会话票据密钥生成器,以便通过我们的全球网络每小时为分布式系统分发新的密钥。每个密钥在被永久删除后都会为用户留存一个自行配置定义的时间(默认为96小时)。分发这些密钥,我们加了一个TLS层到一个key-value( Kyoto Tycoon)的存贮中以便被手工认证TLS的密钥拷贝是已经被完全加密的、并且是由CloudFlare的认证的。有了Kyoto Tycoon, 票据密钥就会在瞬间被全局复制到每个角落的机器。与我们的开源体系相一致,我们计划在Kyoto Tycoon上开源我们的更新版本。随着票据密钥在每一个服务器上的适用,我们能在整个网络的任何机器上重置任何连接。

票据密钥的轮询帮助我们为客户完美的维护了正向加密,当用户用火狐和chrome回访页面时也减少了访问延迟。

会话ID恢复

我们也能用一个会话ID通过多状态机重置会话。不像会话票据,我们仅能在一个数据中心重置会话。这被证明对99.99%的客户都足够好了,因为CloudFlare的选播网络会直接请求最近的数据中心。网民不必特意跨城区访问, 所以大部分重置请求会在一个地方完成。并且,即使最坏的情况下,例如你在一个城市从手机上进入了一个站点,接着你就飞到了另一个城市,你的客户端会轻松重新设置一个新的会话。

Session resumption with session IDs

我们能够从数据中心的一个缓存的会话密钥中,用一个ID重置会话。在中心地区我们会缓存一个会话密钥的加密版本,并用会话ID来索引。如果之前来了一个带有会话ID的新的请求被看到,我们会从任何数据中心的所有服务器中心存贮中纵览它保证它能被进入。这些会话密钥不能离开数据中心后还能留存用户配置有效期(默认96个小时)。会话ID缓存让我们在除了chrome和火狐的浏览器中用一个简短的握手做几乎所有的重置连接尝试。

其他技术顶级组织也用到了会话重置技术。打个比方,谷歌用了类似的技术去对他们的基础设施做重置会话。注意:所有的CloudFlare客户已能够从这种先进的会话重置SSL中获得好处,即使他们没有使用无钥SSL。

开源

CloudFlare开发了许多代码,并在搭建无钥SSL的时候给社区贡献了主要部分的代码。

严格模式SSL: 这里的代码允许从NGINX到验证TLS连接的向上兼容连接,需要为无钥服务器的身份验证所需要。改动被NGINX合并了。

会话票据: 我们在NGINX中为会话票据添加了支持。改动已被NGINX合并。

CFSSL: 最近我们开源了我们内部认证授权的工具。GitHub上已适用。

京都大亨: 我们很快会把相关改动在Kyoto Tycoon上开源, 一个我们扩展的高性能key-value存储, 允许双向的认证。

密钥服务器: 无钥SSL密钥服务器现在在Github已有了参考实现。

为何它很重要

无钥SSL是一个有很大先进性的、允许网站所有者对他们的私钥进行单项控制的时候,去用一个类似CloudFlare的服务以使他们的网站更快更安全。如我们之前在之前提交的声明里所说,Sebastien曾经能一个通宵就构建出初始的无钥SSL原型。但要保证那是安全、快速并且是能被掌控的 -这花费了我们两年的工程时间。现在,随着稳定持久的连接性和先进的会话重置技术,使用无钥SSL将不仅是安全的,而且是极速的!

标签: 密码学, 安全性, 传输层安全tls, 性能, 加密, TLS握手, 会话ID重置, 椭圆曲线, 开源, 无钥SSL, 相关细节, 技术细节, RSA 握手, DH 握手, 短暂的Diffie-Hellman

想学习更多CloudFlare的知识?

获取更多

评论

没有允许js戳这里 comments powered by Disqus. comments powered by Disqus