本周,CloudFlare宣布,开始提供Keyless服务,即你把网站放到它们的CDN上,不用提供本身的私钥,也能使用SSL加密连接。html
我看了CloudFlare的说明(这里和这里),忽然意识到这是绝好的例子,能够用来讲明SSL/TLS协议的运行机制。它配有插图,很容易看懂。算法
下面,我就用这些图片做为例子,配合我半年前写的《SSL/TLS协议运行机制的概述》,来解释SSL协议。浏览器
开始加密通讯以前,客户端和服务器首先必须创建链接和交换参数,这个过程叫作握手(handshake)。安全
假定客户端叫作爱丽丝,服务器叫作鲍勃,整个握手过程能够用下图说明(点击看大图)。服务器
握手阶段分红五步。session
第一步,爱丽丝给出协议版本号、一个客户端生成的随机数(Client random),以及客户端支持的加密方法。less
第二步,鲍勃确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数(Server random)。dom
第三步,爱丽丝确认数字证书有效,而后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给鲍勃。网站
第四步,鲍勃使用本身的私钥,获取爱丽丝发来的随机数(即Premaster secret)。加密
第五步,爱丽丝和鲍勃根据约定的加密方法,使用前面的三个随机数,生成"对话密钥"(session key),用来加密接下来的整个对话过程。
上面的五步,画成一张图,就是下面这样。
握手阶段有三点须要注意。
(1)生成对话密钥一共须要三个随机数。
(2)握手以后的对话使用"对话密钥"加密(对称加密),服务器的公钥和私钥只用于加密和解密"对话密钥"(非对称加密),无其余做用。
(3)服务器公钥放在服务器的数字证书之中。
从上面第二点可知,整个对话过程当中(握手阶段和其后的对话),服务器的公钥和私钥只须要用到一次。这就是CloudFlare可以提供Keyless服务的根本缘由。
某些客户(好比银行)想要使用外部CDN,加快自家网站的访问速度,可是出于安全考虑,不能把私钥交给CDN服务商。这时,彻底能够把私钥留在自家服务器,只用来解密对话密钥,其余步骤都让CDN服务商去完成。
上图中,银行的服务器只参与第四步,后面的对话都再也不会用到私钥了。
整个握手阶段都不加密(也无法加密),都是明文的。所以,若是有人窃听通讯,他能够知道双方选择的加密方法,以及三个随机数中的两个。整个通话的安全,只取决于第三个随机数(Premaster secret)能不能被破解。
虽然理论上,只要服务器的公钥足够长(好比2048位),那么Premaster secret能够保证不被破解。可是为了足够安全,咱们能够考虑把握手阶段的算法从默认的RSA算法,改成 Diffie-Hellman算法(简称DH算法)。
采用DH算法后,Premaster secret不须要传递,双方只要交换各自的参数,就能够算出这个随机数。
上图中,第三步和第四步由传递Premaster secret变成了传递DH算法所需的参数,而后双方各自算出Premaster secret。这样就提升了安全性。
握手阶段用来创建SSL链接。若是出于某种缘由,对话中断,就须要从新握手。
这时有两种方法能够恢复原来的session:一种叫作session ID,另外一种叫作session ticket。
session ID的思想很简单,就是每一次对话都有一个编号(session ID)。若是对话中断,下次重连的时候,只要客户端给出这个编号,且服务器有这个编号的记录,双方就能够从新使用已有的"对话密钥",而没必要从新生成一把。
上图中,客户端给出session ID,服务器确认该编号存在,双方就再也不进行握手阶段剩余的步骤,而直接用已有的对话密钥进行加密通讯。
session ID是目前全部浏览器都支持的方法,可是它的缺点在于session ID每每只保留在一台服务器上。因此,若是客户端的请求发到另外一台服务器,就没法恢复对话。session ticket就是为了解决这个问题而诞生的,目前只有Firefox和Chrome浏览器支持。
上图中,客户端再也不发送session ID,而是发送一个服务器在上一次对话中发送过来的session ticket。这个session ticket是加密的,只有服务器才能解密,其中包括本次对话的主要信息,好比对话密钥和加密方法。当服务器收到session ticket之后,解密后就没必要从新生成对话密钥了。