大型网站的HTTPS实践一Word文件下载.docx
《大型网站的HTTPS实践一Word文件下载.docx》由会员分享,可在线阅读,更多相关《大型网站的HTTPS实践一Word文件下载.docx(15页珍藏版)》请在冰点文库上搜索。
如果劫持技术比较低劣的话,用户甚至无法访问XX。
这里提到的中间者主要指一些网络节点,是用户数据在浏览器和XX服务器中间传输必须要经过的节点。
比如WIFI热点,路由器,防火墙,反向代理,缓存服务器等。
在HTTP协议下,中间者可以随意嗅探用户搜索内容,窃取隐私甚至篡改网页。
不过HTTPS是这些劫持行为的克星,能够完全有效地防御。
总体来说,HTTPS协议提供了三个强大的功能来对抗上述的劫持行为:
1.内容加密。
浏览器到XX服务器的内容都是以加密形式传输,中间者无法直接查看原始内容。
2.身份认证。
保证用户访问的是XX服务,即使被DNS劫持到了第三方站点,也会提醒用户没有访问XX服务,有可能被劫持
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的推导和实现涉及到了欧拉函数和费马定理及模反元素的概念,有兴趣的读者可以自行XX。
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)一般都注册到了证书里,任何人都能直接查看,比如XX证书的公钥对如下图,其中最末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];
}
12345
mastersecrect的生成算法简述如下:
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作为私钥,计算Ys=a^Ksmodp=2^293mod2579=968,把Ys作为公钥发送给client。
3.Client计算共享密钥:
secrect=Ys^(kc)mod(p)=968^123mod(2579)=434
4.Server计算共享密钥:
secrect=Yc^(K_s)mod(p)=2400^293mod(2579)=434
上述公式中的,Y_s,Y_c,P,a,都是公开信息,可以被中间者查看,只有K_(s,)K_c作为私钥没有公开,当私钥较小时,通过穷举攻击能够计算出共享密钥,但是当私钥非常大时,穷举攻击肯定是不可行的。
DH算法有一个比较大的缺陷就是需要提供足够大的私钥来保证安全性,所以比较消耗CPU计算资源。
ECC椭圆曲线算术能够很好的解决这个问题,224位的密钥长度就能达到RSA2048位的安全强度。
ECC的曲线公式描述的其实不是椭圆,只是跟椭圆曲线周长公式形似才叫椭圆曲线加密算术。
ECC涉及到了有限域、群等近世代数的多个概念,就不做详细介绍了。
ECC安全性依赖于这样一个事实:
P=kQ,已知k,Q求出P相对简单,但是已知P和Q求出k却非常困难。
1
上式看起来非常简单,但有如下约束条件:
1.Q是一个非常大的质数,p,k,q都是椭圆曲线有限域上的离散点。
2.有限域定义了自己的加法和乘法法则,即使kQ的运算也非常复杂。
ECC应用于Diffie-Hellman密钥交换过程如下:
1.定义一个满足椭圆方程的有限域,即挑选p,a,b满足如下方程:
y^2modp=(x^3+ax+b)modp
2.挑选基点G=(x,y),G的阶为n。
n为满足nG=0的最小正整数。
3.Client选择私钥K_(c)(0<
K_(c
4.server选择私钥K_(s)并产生公钥Y_s=K_s×
G
5.client计算共享密钥K=K_c×
Y_s,server端计算共享密钥K_s×
Y_c,这两者的结果是一样的,因为:
K_c×
Y_s=K_c×
(K_(s)×
G)=K_s×
(K_(c)×
Y_c1
由上面描述可知,只要确定p,a,b就能确定一条有限域上的椭圆曲线,由于不是所有的椭圆曲线都能够用于加密,所以p,a,b的选取非常讲究,直接关系曲线的安全性和计算速度。
Openssl实现的,也是FIPS推荐的256位素数域上的椭圆曲线参数定义如下:
质数p=115792089210356248762697446949407573530086143415290314195533631308867097853951
阶n=115792089210356248762697446949407573529996955224135760342422259061068512044369
SEED=c49d360886e704936a6678e1139d26b7819f7e90
c=7efba1662985be9403cb055c75d4f7e0ce8d84a9c5114abcaf3177680104fa0d
椭圆曲线的系数a=0
椭圆曲线的系统b=5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
基点Gx=6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
基点Gy=4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5
123456789
4.1.1.2.2握手过程中的ECDHE密钥协商
简单介绍了ECC和DH算法的数学原理,我们看下ECDHE在TLS握手过程中的应用。
相比RSA,ECDHE需要多发送一个server_key_exchange的握手消息才能完成密钥协商。
同样以TLS1.2为例,简单描述一下过程:
1.浏览器发送client_hello,包含一个随机数random1,同时需要有2个扩展:
a)Elliptic_curves:
客户端支持的曲线类型和有限域参数。
现在使用最多的是256位的素数域,参数定义如上节所述。
b)Ec_point_formats:
支持的曲线点格式,默认都是uncompressed。
2,服务端回复server_hello,包含一个随机数random2及ECC扩展。
3,服务端回复certificate,携带了证书公钥。
4,服务端生成ECDH临时公钥,同时回复server_key_exchange,包含三部分重要内容:
a)ECC相关的参数。
b)ECDH临时公钥。
c)ECC参数和公钥生成的签名值,用于客户端校验。
5,浏览器接收server_key_exchange之后,使用证书公钥进行签名解密和校验,获取服务器端的ECDH临时公钥,生成会话所需要的共享密钥。
至此,浏览器端完成了密钥协商。
6,浏览器生成ECDH临时公钥和client_key_exchange消息,跟RSA密钥协商不同的是,这个消息不需要加密了。
7,服务器处理client_key_exchang消息,获取客户端ECDH临时公钥。
8,服务器生成会话所需要的共享密钥。
9,Server端密钥协商过程结束。
图示如下:
4.1.2对称内容加密
非对称密钥交换过程结束之后就得出了本次会话需要使用的对称密钥。
对称加密又分为两种模式:
流式加密和分组加密。
流式加密现在常用的就是RC4,不过RC4已经不再安全,微软也建议网站尽量不要使用RC4流式加密。
一种新的替代RC4的流式加密算法叫ChaCha20,它是google推出的速度更快,更安全的加密算法。
目前已经被android和chrome采用,也编译进了google的开源openssl分支—boringssl,并且nginx1.7.4也支持编译boringssl。
分组加密以前常用的模式是AES-CBC,但是CBC已经被证明容易遭受BEAST和LUCKY13攻击。
目前建议使用的分组加密模式是AES-GCM,不过它的缺点是计算量大,性能和电量消耗都比较高,不适用于移动电话和平板电脑。
4.2身份认证
身份认证主要涉及到PKI和数字证书。
通常来讲PKI(公钥基础设施)包含如下部分:
Endentity:
终端实体,可以是一个终端硬件或者网站。
CA:
证书签发机构。
RA:
证书注册及审核机构。
比如审查申请网站或者公司的真实性。
CRLissuer:
负责证书撤销列表的发布和维护。
Repository:
负责数字证书及CRL内容存储和分发。
申请一个受信任的数字证书通常有如下流程:
终端实体生成公私钥和证书请求。
RA检查实体的合法性。
如果个人或者小网站,这一步不是必须的。
CA签发证书,发送给申请者。
证书更新到repository,终端后续从repository更新证书,查询证书状态等。
目前XX使用的证书是X509v3格式,由如下三个部分组成:
tbsCertificate(tobesignedcertificate待签名证书内容),这部分包含了10个要素,分别是版本号,序列号,签名算法标识,发行者名称,有效期,证书主体名,证书主体公钥信息,发行商唯一标识,主体唯一标识,扩展等。
signatureAlgorithm,签名算法标识,指定对tbsCertificate进行签名的算法。
signaturValue(签名值),使用signatureAlgorithm对tbsCertificate进行计算得到签名值。
数字证书有两个作用:
身份授权。
确保浏览器访问的网站是经过CA验证的可信任的网站。
分发公钥。
每个数字证书都包含了注册者生成的公钥。
在SSL握手时会通过certificate消息传输给客户端。
比如前文提到的RSA证书公钥加密及ECDHE的签名都是使用的这个公钥。
申请者拿到CA的证书并部署在网站服务器端,那浏览器发起握手接收到证书后,如何确认这个证书就是CA签发的呢?
怎样避免第三方伪造这个证书?
答案就是数字签名(digitalsignature)。
数字签名是证书的防伪标签,目前使用最广泛的SHA-RSA数字签名的制作和验证过程如下:
数字签名的签发。
首先是使用哈希函数对待签名内容进行安全哈希,生成消息摘要,然后使用CA自己的私钥对消息摘要进行加密。
数字签名的校验。
使用CA的公钥解密签名,然后使用相同的签名函数对待签名证书内容进行签名并和服务端数字签名里的签名内容进行比较,如果相同就认为校验成功。
这里有几点需要说明:
1.数字签名签发和校验使用的密钥对是CA自己的公私密钥,跟证书申请者提交的公钥没有关系。
2.数字签名的签发过程跟公钥加密的过程刚好相反,即是用私钥加密,公钥解密。
3.现在大的CA都会有证书链,证书链的好处一是安全,保持根CA的私钥离线使用。
第二个好处是方便部署和撤销,即如果证书出现问题,只需要撤销相应级别的证书,根证书依然安全。
4.根CA证书都是自签名,即用自己的公钥和私钥完成了签名的制作和验证。
而证书链上的证书签名都是使用上一级证书的密钥对完成签名和验证的。
5.怎样获取根CA和多级CA的密钥对?
它们是否可信?
当然可信,因为这些厂商跟浏览器和操作系统都有合作,它们的公钥都默认装到了浏览器或者操作系统环境里。
比如firefox就自己维护了一个可信任的CA列表,而chrome和IE使用的是操作系统的CA列表。
4.3数据完整性
这部分内容比较好理解,跟平时的md5签名类似,只不过安全要求要高很多。
openssl现在使用的完整性校验算法有两种:
MD5或者SHA。
由于MD5在实际应用中存在冲突的可能性比较大,所以尽量别采用MD5来验证内容一致性。
SHA也不能使用SHA0和SHA1,中国山东大学的王小云教授在2005年就宣布破解了SHA-1完整版算法。
微软和google都已经宣布16年及17年之后不再支持sha1签名证书。
5HTTPS使用成本
HTTPS目前唯一的问题就是它还没有得到大规模应用,受到的关注和研究都比较少。
至于使用成本和额外开销,完全不用太过担心。
一般来讲,使用HTTPS前大家可能会非常关注如下问题:
1.证书费用以及更新维护。
大家觉得申请证书很麻烦,证书也很贵,可是证书其实一点都不贵,便宜的一年几十块钱,最多也就几百。
而且现在也有了免费的证书机构,比如著名的mozill