大型网站的HTTPS实践(一)1前言百度已经于近日上线了全站HTTPS的安全搜索,默认会将HTTP请求跳转成HTTPS。本文重点介绍HTTPS协议,并简单介绍部署全站HTTPS的意义。本文转载自百度运维部官方博客2HTTPS协议概述HTTPS可以认为是HTTP+TLS。HTTP协议大家耳熟能详了,目前大部分WEB应用和网站都是使用HTTP协议传输的。TLS是传输层加密协议,它的前身是SSL协议,最早由netscape公司于1995年发布,1999年经过IETF讨论和规范后,改名为TLS。如果没有特别说明,SSL和TLS说的都是同一个协议。HTTP和TLS在协议层的位置以及TLS协议的组成如下图:TLS协议主要有五部分:应用数据层协议,握手协议,报警协议,加密消息确认协议,心跳协议。TLS协议本身又是由record协议传输的,record协议的格式如上图最右所示。目前常用的HTTP协议是HTTP1.1,常用的TLS协议版本有如下几个:TLS1.2,TLS1.1,TLS1.0和SSL3.0。其中SSL3.0由于POODLE攻击已经被证明不安全,但统计发现依然有不到1%的浏览器使用SSL3.0。TLS1.0也存在部分安全漏洞,比如RC4和BEAST攻击。TLS1.2和TLS1.1暂时没有已知的安全漏洞,比较安全,同时有大量扩展提升速度和性能,推荐大家使用。需要关注一点的就是TLS1.3将会是TLS协议一个非常重大的改革。不管是安全性还是用户访问速度都会有质的提升。不过目前没有明确的发布时间。同时HTTP2也已经正式定稿,这个由SPDY协议演化而来的协议相比HTTP1.1又是一个非常重大的变动,能够明显提升应用层数据的传输效率。3HTTPS功能介绍百度使用HTTPS协议主要是为了保护用户隐私,防止流量劫持。HTTP本身是明文传输的,没有经过任何安全处理。例如用户在百度搜索了一个关键字,比如“苹果手机”,中间者完全能够查看到这个信息,并且有可能打电话过来骚扰用户。也有一些用户投诉使用百度时,发现首页或者结果页面浮了一个很长很大的广告,这也肯定是中间者往页面插的广告内容。如果劫持技术比较低劣的话,用户甚至无法访问百度。这里提到的中间者主要指一些网络节点,是用户数据在浏览器和百度服务器中间传输必须要经过的节点。比如WIFI热点,路由器,防火墙,反向代理,缓存服务器等。在HTTP协议下,中间者可以随意嗅探用户搜索内容,窃取隐私甚至篡改网页。不过HTTPS是这些劫持行为的克星,能够完全有效地防御。总体来说,HTTPS协议提供了三个强大的功能来对抗上述的劫持行为:1.内容加密。浏览器到百度服务器的内容都是以加密形式传输,中间者无法直接查看原始内容。2.身份认证。保证用户访问的是百度服务,即使被DNS劫持到了第三方站点,也会提醒用户没有访问百度服务,有可能被劫持3.数据完整性。防止内容被第三方冒充或者篡改。那HTTPS是如何做到上述三点的呢?下面从原理角度介绍一下。4HTTPS原理介绍4.1内容加密加密算法一般分为两种,对称加密和非对称加密。所谓对称加密(也叫密钥加密)就是指加密和解密使用的是相同的密钥。而非对称加密(也叫公钥加密)就是指加密和解密使用了不同的密钥。对称内容加密强度非常高,一般破解不了。但存在一个很大的问题就是无法安全地生成和保管密钥。假如客户端软件和服务器之间每次会话都使用固定的,相同的密钥加密和解密,肯定存在很大的安全隐患。如果有人从客户端端获取到了对称密钥,整个内容就不存在安全性了,而且管理海量的客户端密钥也是一件很复杂的事情。非对称加密主要用于密钥交换(也叫密钥协商),能够很好地解决这个问题。浏览器和服务器每次新建会话时都使用非对称密钥交换算法协商出对称密钥,使用这些对称密钥完成应用数据的加解密和验证,整个会话过程中的密钥只在内存中生成和保存,而且每个会话的对称密钥都不相同(除非会话复用),中间者无法窃取。非对称密钥交换很安全,但同时也是HTTPS性能和速度严重降低的“罪魁祸首”。想要知道HTTPS为什么影响速度,为什么消耗资源,就一定要理解非对称密钥交换的整个过程。下面重点介绍一下非对称密钥交换的数学原理及在TLS握手过程中的应用。4.1.1非对称密钥交换在非对称密钥交换算法出现以前,对称加密一个很大的问题就是不知道如何安全生成和保管密钥。非对称密钥交换过程主要就是为了解决这个问题,使得对称密钥的生成和使用更加安全。密钥交换算法本身非常复杂,密钥交换过程涉及到随机数生成,模指数运算,空白补齐,加密,签名等操作。常见的密钥交换算法有RSA,ECDHE,DH,DHE等算法。它们的特性如下:RSA:算法实现简单,诞生于1977年,历史悠久,经过了长时间的破解测试,安全性高。缺点就是需要比较大的素数(目前常用的是2048位)来保证安全强度,很消耗CPU运算资源。RSA是目前唯一一个既能用于密钥交换又能用于证书签名的算法。DH:diffie-hellman密钥交换算法,诞生时间比较早(1977年),但是1999年才公开。缺点是比较消耗CPU性能。ECDHE:使用椭圆曲线(ECC)的DH算法,优点是能用较小的素数(256位)实现RSA相同的安全等级。缺点是算法实现复杂,用于密钥交换的历史不长,没有经过长时间的安全攻击测试。ECDH:不支持PFS,安全性低,同时无法实现falsestart。建议优先支持RSA和ECDH_RSA密钥交换算法。原因是:1.ECDHE支持ECC加速,计算速度更快。支持PFS,更加安全。支持falsestart,用户访问速度更快。2.目前还有至少20%以上的客户端不支持ECDHE,我们推荐使用RSA而不是DH或者DHE,因为DH系列算法非常消耗CPU(相当于要做两次RSA计算)。需要注意通常所说的ECDHE密钥交换默认都是指ECDHE_RSA,使用ECDHE生成DH算法所需的公私钥,然后使用RSA算法进行签名最后再计算得出对称密钥。非对称加密相比对称加密更加安全,但也存在两个明显缺点:1.CPU计算资源消耗非常大。一次完全TLS握手,密钥交换时的非对称解密计算量占整个握手过程的90%以上。而对称加密的计算量只相当于非对称加密的0.1%,如果应用层数据也使用非对称加解密,性能开销太大,无法承受。2.非对称加密算法对加密内容的长度有限制,不能超过公钥长度。比如现在常用的公钥长度是2048位,意味着待加密内容不能超过256个字节。所以公钥加密目前只能用来作密钥交换或者内容签名,不适合用来做应用层传输内容的加解密。非对称密钥交换算法是整个HTTPS得以安全的基石,充分理解非对称密钥交换算法是理解HTTPS协议和功能的关键。下面分别通俗地介绍一下RSA和ECDHE在密钥交换过程中的应用。4.1.1.1RSA密钥协商4.1.1.1.1RSA算法介绍RSA算法的安全性是建立在乘法不可逆或者大数因子很难分解的基础上。RSA的推导和实现涉及到了欧拉函数和费马定理及模反元素的概念,有兴趣的读者可以自行百度。RSA算法是统治世界的最重要算法之一,而且从目前来看,RSA也是HTTPS体系中最重要的算法,没有之一。RSA的计算步骤如下:随机挑选两个质数p,q,假设p=13,q=19。n=p*q=13*19=247。(n)表示与整数n互质数的个数。如果n等于两个质数的积,则?(n)=(p-1)*(q-1)挑选一个数e,满足1计算e关于n的模反元素,ed≡1mod?(n),由e=17,?(n)=216可得d=89实际应用中,(n,e)组成了公钥对,(n,d)组成了私钥对,其中n和d都是一个接近2^2048的大数。即使现在性能很强的CPU,想要计算〖m≡c〗^dmod(n),也需要消耗比较大的计算资源和时间。公钥对(n,e)一般都注册到了证书里,任何人都能直接查看,比如百度证书的公钥对如下图,其中最末6个数字(010001)换算成10进制就是65537,也就是公钥对中的e。e取值比较小的好处有两个:由c=m^emod(n)可知,e较小,客户端CPU计算消耗的资源较少。加大server端的破解难度。e比较小,私钥对中的d必然会非常大。所以d的取值空间也就非常大,增加了破解难度。那为什么(n,e)能做为公钥公开,甚至大家都能直接从证书中查看到,这样安全吗?分析如下:由于ed≡1mod?(n),知道了e和n,想要求出私钥d,就必须知道?(n)。而?(n)=(p-1)*(q-1),必须计算出p和q才能确定私钥d。但是当n大到一定程度时(比如接近2^2048),即使现在最快的CPU也无法进行这个因式分解,即无法知道n是由哪个数p和q乘出来的。所以就算知道了公钥,整个加解密过程还是非常安全的。4.1.1.1.2握手过程中的RSA密钥协商介绍完了RSA的原理,那最终会话所需要的对称密钥是如何生成的呢?跟RSA有什么关系?以TLS1.2为例简单描述一下,省略跟密钥交换无关的握手消息。过程如下:浏览器发送client_hello,包含一个随机数random1。服务端回复server_hello,包含一个随机数random2,同时回复certificate,携带了证书公钥P。浏览器接收到random2之后就能够生成premaster_secrect以及master_secrect。其中premaster_secret长度为48个字节,前2个字节是协议版本号,剩下的46个字节填充一个随机数。结构如下:Struct{byteVersion[2];buterandom[46];}12345mastersecrect的生成算法简述如下:Master_key=PRF(premaster_secret,“mastersecrect”,随机数1+随机数2)其中PRF是一个随机函数,定义如下:PRF(secret,label,seed)=P_MD5(S1,label+seed)XORP_SHA-1(S2,label+seed)123456从上式可以看出,把premaster_key赋值给secret,”masterkey”赋值给label,浏览器和服务器端的两个随机数做种子就能确定地求出一个48位长的随机数。而mastersecrect包含了六部分内容,分别是用于校验内容一致性的密钥,用于对称内容加解密的密钥,以及初始化向量(用于CBC模式),客户端和服务端各一份。至此,浏览器侧的密钥已经完成协商。浏览器使用证书公钥P将premaster_secrect加密后发送给服务器。服务端使用私钥解密得到premaster_secrect。又由于服务端之前就收到了随机数1,所以服务端根据相同的生成算法,在相同的输入参数下,求出了相同的mastersecrect。RSA密钥协商握手过程图示如下:可以看出,密钥协商过程需要2个RTT,这也是HTTPS慢的一个重要原因。而RSA发挥的关键作用就是对premaster_secrect进行了加密和解密。中间者不可能破解RSA算法,也就不可能知道premaster_secrect,从而保证了密钥协商过程的安全性。4.1.1.2ECDHE密钥协商4.1.1.2.1DH与ECC算法原理ECDHE算法实现要复杂很多,主要分为两部分:diffie-hellman算法(简称为DH)及ECC(椭圆曲线算术)。他们的安全性都是建立在离散对数计算很困难的基础上。简单介绍一下dh算法的实现,先介绍两个基本概念:本原根:如果整数a是素数p的本原根,则a,a^2,…,a^(p-1)在modp下都不相同。离散对数:对任意整数b和素数p的本原根a,存在唯一的指数i满足b≡a^imodp(0≤i≤p-1)1则称i是b的以a为底的模p的离散对数。理解这两个概念,dh算法就非常简单了,示例如下:假设client和server需要协商密钥,p=2579,则本原根a=2。1.Client选择随机数Kc=123做为自己的私钥,计算Yc=a^Kcmodp=2^123mod2579=2400,把Yc作为公钥发送给server。2.Server选择随机数Ks=293作为私钥,