HTTPS 协议概述
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 协议一个非常重大的改革。不管是安全性还是用户访问速度都会有质的提升。不过目前没有明确的发布时间。
HTTPS 功能介绍
百度使用 HTTPS 协议主要是为了保护用户隐私,防止流量劫持。
HTTP 本身是明文传输的,没有经过任何安全处理。例如用户在百度搜索了一个关键字,比如 “苹果手机”,中间者完全能够查看到这个信息,并且有可能打电话过来骚扰用户。也有一些用户投诉使用百度时,发现首页或者结果页面浮了一个很长很大的广告,这也肯定是中间者往页面插的广告内容。如果劫持技术比较低劣的话,用户甚至无法访问百度。
这里提到的中间者主要指一些网络节点,是用户数据在浏览器和百度服务器中间传输必须要经过的节点。比如 WIFI 热点,路由器,防火墙,反向代理,缓存服务器等。
在 HTTP 协议下,中间者可以随意嗅探用户搜索内容,窃取隐私甚至篡改网页。不过 HTTPS 是这些劫持行为的克星,能够完全有效地防御。
总体来说,HTTPS 协议提供了三个强大的功能来对抗上述的劫持行为:
内容加密:浏览器到百度服务器的内容都是以加密形式传输,中间者无法直接查看原始内容。
身份认证:保证用户访问的是百度服务,即使被 DNS 劫持到了第三方站点,也会提醒用户没有访问百度服务,有可能被劫持
数据完整性:防止内容被第三方冒充或者篡改。
那 HTTPS 是如何做到上述三点的呢?下面从原理角度介绍一下。
HTTPS 原理介绍
1. 内容加密
加密算法一般分为两种,对称加密和非对称加密。所谓对称加密(也叫密钥加密)就是指加密和解密使用的是相同的密钥。而非对称加密(也叫公钥加密)就是指加密和解密使用了不同的密钥。
非对称密钥交换
在非对称密钥交换算法出现以前,对称加密一个很大的问题就是不知道如何安全生成和保管密钥。非对称密钥交换过程主要就是为了解决这个问题,使得对称密钥的生成和使用更加安全。
密钥交换算法本身非常复杂,密钥交换过程涉及到随机数生成,模指数运算,空白补齐,加密,签名等操作。
常见的密钥交换算法有 RSA,ECDHE,DH,DHE 等算法。它们的特性如下:
RSA:算法实现简单,诞生于 1977 年,历史悠久,经过了长时间的破解测试,安全性高。缺点就是需要比较大的素数(目前常用的是 2048 位)来保证安全强度,很消耗 CPU 运算资源。RSA 是目前唯一一个既能用于密钥交换又能用于证书签名的算法。
DH:diffie-hellman 密钥交换算法,诞生时间比较早(1977 年),但是 1999 年才公开。缺点是比较消耗 CPU 性能。
ECDHE:使用椭圆曲线(ECC)的 DH 算法,优点是能用较小的素数(256 位)实现 RSA 相同的安全等级。缺点是算法实现复杂,用于密钥交换的历史不长,没有经过长时间的安全攻击测试。
ECDH:不支持 PFS,安全性低,同时无法实现 false start。
DHE:不支持 ECC。非常消耗性能。
百度只支持 RSA 和 ECDH_RSA 密钥交换算法。原因是:
ECDHE 支持 ECC 加速,计算速度更快。支持 PFS,更加安全。支持 false start,用户访问速度更快。
目前还有至少 20% 以上的客户端不支持 ECDHE,我们推荐使用 RSA 而不是 DH 或者 DHE,因为 DH 系列算法非常消耗 CPU(相当于要做两次 RSA 计算)。
需要注意通常所说的 ECDHE 密钥交换默认都是指 ECDHE_RSA,使用 ECDHE 生成 DH 算法所需的公私钥,然后使用 RSA 算法进行签名最后再计算得出对称密钥。
非对称加密相比对称加密更加安全,但也存在两个明显缺点:
CPU 计算资源消耗非常大。一次完全 TLS 握手,密钥交换时的非对称解密计算量占整个握手过程的 90% 以上。而对称加密的计算量只相当于非对称加密的 0.1%,如果应用层数据也使用非对称加解密,性能开销太大,无法承受。
非对称加密算法对加密内容的长度有限制,不能超过公钥长度。比如现在常用的公钥长度是 2048 位,意味着待加密内容不能超过 256 个字节。
所以公钥加密目前只能用来作密钥交换或者内容签名,不适合用来做应用层传输内容的加解密。
非对称密钥交换算法是整个 HTTPS 得以安全的基石,充分理解非对称密钥交换算法是理解 HTTPS 协议和功能的关键。
下面分别通俗地介绍一下 RSA 和 ECDHE 在密钥交换过程中的应用。
RSA 在密钥交换过程中的应用
RSA 算法的原理是乘法不可逆或者大数因子很难分解。RSA 的推导实现涉及到了欧拉函数和费马定理及模反元素的概念,有兴趣的读者可以自行百度。
RSA 算法是统治世界的最重要算法之一,而且从目前来看,RSA 也是 HTTPS 体系中最重要的算法,没有之一。 下面用一个简单的示例介绍一下 RSA 的神奇妙用。
假设一个网站需要使用 HTTPS 协议,那么它首先就得申请数字证书,申请证书之前需要生成一对公钥和私钥,为了方便说明问题,假设 server 的密钥长度只有 8 位,事实上现在的服务器证书至少是 2048 位长。随机挑选两个质数 p, q,使得 pq 接近 2 的 8 次方 = 256, 假设 p = 13, q = 19。n = pq = 13*19 = 247。
挑选一个数 e,满足 1< e < (p-1)(q-1) 并且 e 与 (p-1)(q-1) 互质,假设 e = 53。
计算 e 关于 n 的模反元素 , ed≡1 (mod φ(n)), d =
实际应用中,(n,e) 组成了公钥对,(n,d)组成了私钥对。公钥一般都注册到了证书里,任何人都能直接查看,比如百度证书的公钥对如下图,其中最末 6 个数字(010001)换算成 10 进制就是 65537,也就是公钥对中的 e, 取值比较小的原因有两个:
减小 client 端的计算强度,特别是现在移动终端的计算能力比较弱,较小的公钥使得 CPU 计算会更快。
加大 server 端的破解难度。e 比较小,d 必然会非常大。所以 d 的取值空间也会非常大。
ECDHE 算法在密钥交换中的应用
ECDHE 算法实现要复杂很多,依赖的数学原理主要是 ECC 椭圆曲线和离散对数。详细概念不做说明,示例介绍一下。
对称内容加密
非对称密钥交换过程结束之后就得出了本次会话需要使用的对称密钥。对称加密又分为两种模式:流式加密和分组加密。流式加密现在常用的就是 RC4,不过 RC4 已经不再安全,微软也建议网站尽量不要使用 RC4 流式加密。
一种新的替代 RC4 的流式加密算法叫 ChaCha20,它是 google 推出的速度更快,更安全的加密算法。目前已经被 android 和 chrome 采用,也编译进了 google 的开源 openssl 分支---boring ssl,并且 nginx 1.7.4 也支持编译 boringssl。
分组加密以前常用的模式是 AES-CBC,但是 CBC 已经被证明容易遭受 BEAST 和 LUCKY13 攻击。目前建议使用的分组加密模式是 AES-GCM,不过它的缺点是计算量大,性能和电量消耗都比较高,不适用于移动电话和平板电脑。
数据完整性
这部分内容比较好理解,跟平时的 md5 签名类似,只不过安全要求要高很多。openssl 现在使用的完整性校验算法有两种:MD5 或者 SHA。由于 MD5 在实际应用中存在冲突的可能性比较大,所以尽量别采用 MD5 来验证内容一致性。SHA 也不能使用 SHA0 和 SHA1,中国山东大学的王小云教授在 2005 年就宣布破解了 SHA-1 完整版算法。
微软和 google 都已经宣布 16 年及 17 年之后不再支持 sha1 签名证书。
身份认证
身份认证主要涉及到 PKI 和数字证书。数字证书有两个作用:
身份授权。确保浏览器访问的网站是经过 CA 验证的可信任的网站。
分发公钥。每个数字证书都包含了注册者生成的公钥。在 SSL 握手时会通过 certificate 消息传输给客户端。
这里简单介绍一下数字证书是如何验证网站身份的,PKI 体系的具体知识不做详细介绍。
证书申请者首先会生成一对密钥,包含公钥和密钥,然后把公钥及域名还有 CU 等资料制作成 CSR 格式的请求发送给 RA,RA 验证完这些内容之后(RA 会请独立的第三方机构和律师团队确认申请者的身份)再将 CSR 发送给 CA,CA 然后制作 X.509 格式的证书。
申请者拿到 CA 的证书并部署在网站服务器端,那浏览器发起握手接收到证书后,如何确认这个证书就是 CA 签发的呢?怎样避免第三方伪造这个证书?
答案就是数字签名(digital signature)。数字签名可以认为是一个证书的防伪标签,目前使用最广泛的 SHA-RSA 数字签名的制作和验证过程如下:
数字签名的签发。首先是使用哈希函数对证书数据哈希,生成消息摘要,然后使用 CA 自己的私钥对证书内容和消息摘要进行加密。
数字签名的校验。使用 CA 的公钥解密签名,然后使用相同的签名函数对证书内容进行签名并和服务端的数字签名里的签名内容进行比较,如果相同就认为校验成功。
这里有几点需要说明:
数字签名签发和校验使用的密钥对是 CA 自己的公私密钥,跟证书申请者提交的公钥没有关系。
数字签名的签发过程跟公钥加密的过程刚好相反,即是用私钥加密,公钥解密。
现在大的 CA 都会有证书链,证书链的好处一是安全,保持根 CA 的私钥离线使用。第二个好处是方便部署和撤销,即如何证书出现问题,只需要撤销相应级别的证书,根证书依然安全。
根 CA 证书都是自签名,即用自己的公钥和私钥完成了签名的制作和验证。而证书链上的证书签名都是使用上一级证书的密钥对完成签名和验证的。
怎样获取根 CA 和多级 CA 的密钥对?它们是否可信?当然可信,因为这些厂商跟浏览器和操作系统都有合作,它们的公钥都默认装到了浏览器或者操作系统环境里。比如 firefox 就自己维护了一个可信任的 CA 列表,而 chrome 和 IE 使用的是操作系统的 CA 列表。
HTTPS 使用成本
HTTPS 目前唯一的问题就是它还没有得到大规模应用,受到的关注和研究都比较少。至于使用成本和额外开销,完全不用太过担心。
一般来讲,使用 HTTPS 前大家可能会非常关注如下问题:
证书费用以及更新维护。大家觉得申请证书很麻烦,证书也很贵,可是证书其实一点都不贵,便宜的一年几十块钱,最多也就几百。而且现在也有了免费的证书机构,比如著名的 mozilla 发起的免费证书项目:let’s encrypt就支持免费证书安装和自动更新。这个项目将于今年中旬投入正式使用。 数字证书的费用其实也不高,对于中小网站可以使用便宜甚至免费的数字证书服务(可能存在安全隐患),像著名的 verisign 公司的证书一般也就几千到几万块一年不等。当然如果公司对证书的需求比较大,定制性要求高,可以建立自己的 CA 站点,比如 google,能够随意签发 google 相关证书。
HTTPS 降低用户访问速度。HTTPS 对速度会有一定程度的降低,但是只要经过合理优化和部署,HTTPS 对速度的影响完全可以接受。在很多场景下,HTTPS 速度完全不逊于 HTTP,如果使用 SPDY,HTTPS 的速度甚至还要比 HTTP 快。 大家现在使用百度 HTTPS 安全搜索,有感觉到慢吗?
HTTPS 消耗 CPU 资源,需要增加大量机器。前面介绍过非对称密钥交换,这是消耗 CPU 计算资源的大户,此外,对称加解密,也需要 CPU 的计算。 同样地,只要合理优化,HTTPS 的机器成本也不会明显增加。对于中小网站,完全不需要增加机器也能满足性能需求。
HTTPS 对访问速度的影响
在介绍速度优化策略之前,先来看下 HTTPS 对速度有什么影响。影响主要来自两方面:
协议交互所增加的网络 RTT(round trip time)。
加解密相关的计算耗时。
下面分别介绍一下。
网络耗时增加
由于 HTTP 和 HTTPS 都需要 DNS 解析,并且大部分情况下使用了 DNS 缓存,为了突出对比效果,忽略主域名的 DNS 解析时间。
用户使用 HTTP 协议访问 http://www.baidu.com(或者 www.baidu.com) 时会有如下网络上的交互耗时:
图 1 HTTP 首个请求的网络耗时
可见,用户只需要完成 TCP 三次握手建立 TCP 连接就能够直接发送 HTTP 请求获取应用层数据,此外在整个访问过程中也没有需要消耗计算资源的地方。
接下来看 HTTPS 的访问过程,相比 HTTP 要复杂很多,在部分场景下,使用 HTTPS 访问有可能增加 7 个 RTT。如下图:
图 2 HTTPS 首次请求对访问速度的影响
HTTPS 首次请求需要的网络耗时解释如下:
三次握手建立 TCP 连接。耗时一个 RTT。
使用 HTTP 发起 GET 请求,服务端返回 302 跳转到 https://www.baidu.com 。需要一个 RTT 以及 302 跳转延时。
大部分情况下用户不会手动输入 https://www.baidu.com 来访问 HTTPS,服务端只能返回 302 强制浏览器跳转到 https。
浏览器处理 302 跳转也需要耗时。
三次握手重新建立 TCP 连接。耗时一个 RTT。
302 跳转到 HTTPS 服务器之后,由于端口和服务器不同,需要重新完成三次握手,建立 TCP 连接。
TLS 完全握手阶段一。耗时至少一个 RTT。
这个阶段主要是完成加密套件的协商和证书的身份认证。
服务端和浏览器会协商出相同的密钥交换算法、对称加密算法、内容一致性校验算法、证书签名算法、椭圆曲线(非 ECC 算法不需要)等。
浏览器获取到证书后需要校验证书的有效性,比如是否过期,是否撤销。
解析 CA 站点的 DNS。耗时一个 RTT。
浏览器获取到证书后,有可能需要发起 OCSP 或者 CRL 请求,查询证书状态。
浏览器首先获取证书里的 CA 域名。
如果没有命中缓存,浏览器需要解析 CA 域名的 DNS。
三次握手建立 CA 站点的 TCP 连接。耗时一个 RTT。
DNS 解析到 IP 后,需要完成三次握手建立 TCP 连接。
发起 OCSP 请求,获取响应。耗时一个 RTT。
完全握手阶段二,耗时一个 RTT 及计算时间。
完全握手阶段二主要是密钥协商。
完全握手结束后,浏览器和服务器之间进行应用层(也就是 HTTP)数据传输。
当然不是每个请求都需要增加 7 个 RTT 才能完成 HTTPS 首次请求交互。大概只有不到 0.01% 的请求才有可能需要经历上述步骤,它们需要满足如下条件:
必须是首次请求。即建立 TCP 连接后发起的第一个请求,该连接上的后续请求都不需要再发生上述行为。
必须要发生完全握手,而正常情况下 80% 的请求能实现简化握手。
浏览器需要开启 OCSP 或者 CRL 功能。Chrome 默认关闭了 ocsp 功能,firefox 和 IE 都默认开启。
浏览器没有命中 OCSP 缓存。Ocsp 一般的更新周期是 7 天,firefox 的查询周期也是 7 天,也就说是 7 天中才会发生一次 ocsp 的查询。
浏览器没有命中 CA 站点的 DNS 缓存。只有没命中 DNS 缓存的情况下才会解析 CA 的 DNS。
2.2 计算耗时增加
上节还只是简单描述了 HTTPS 关键路径上必须消耗的纯网络耗时,没有包括非常消耗 CPU 资源的计算耗时,事实上计算耗时也不小(30ms 以上),从浏览器和服务器的角度分别介绍一下:
浏览器计算耗时
RSA 证书签名校验,浏览器需要解密签名,计算证书哈希值。如果有多个证书链,浏览器需要校验多个证书。
RSA 密钥交换时,需要使用证书公钥加密 premaster。耗时比较小,但如果手机性能比较差,可能也需要 1ms 的时间。
ECC 密钥交换时,需要计算椭圆曲线的公私钥。
ECC 密钥交换时,需要使用证书公钥解密获取服务端发过来的 ECC 公钥。
ECC 密钥交换时,需要根据服务端公钥计算 master key。
应用层数据对称加解密。
应用层数据一致性校验。
服务端计算耗时
RSA 密钥交换时需要使用证书私钥解密 premaster。这个过程非常消耗性能。
ECC 密钥交换时,需要计算椭圆曲线的公私钥。
ECC 密钥交换时,需要使用证书私钥加密 ECC 的公钥。
ECC 密钥交换时,需要根据浏览器公钥计算共享的 master key。
应用层数据对称加解密。
应用层数据一致性校验。
由于客户端的 CPU 和操作系统种类比较多,所以计算耗时不能一概而论。手机端的 HTTPS 计算会比较消耗性能,单纯计算增加的延迟至少在 50ms 以上。PC 端也会增加至少 10ms 以上的计算延迟。
服务器的性能一般比较强,但由于 RSA 证书私钥长度远大于客户端,所以服务端的计算延迟也会在 5ms 以上。
转载自:https://developer.baidu.com/resources/online/doc/security/https-pratice-1.html