HTTPS 技术揭秘

184 阅读22分钟

前言

随着互联网技术的发展,网络安全是极其重要的一环,说起网络安全,大家肯定能第一时间想到使用 HTTPS,这应该也是最简单有效的方法。HTTP2 也强制只支持 HTTPS 协议,在信息安全如此重要的现在和未来,可以预见未来所有网站都会使用 HTTPS。

本文将向大家介绍 HTTPS 确保数据安全传输背后的原理。

HTTPS 出现背景,解决了什么问题

HTTP 明文传输隐患

HTTP 协议的诞生主要是为了解决信息传递和共享的问题,并没有考虑到互联网高速发展后面临的安全问题,HTTP 协议不具备任何数据加密、身份校验等机制,也就是数据都是明文传输的。这样的话,在传输过程中的每一个环节,数据都有可能被窃取或者篡改,这也意味着浏览器和服务器之间还可能有个中间人,他们在通信过程中的一切内容都在中间人的掌握中,如下图:

从上图可以看出,我们使用 HTTP 传输的内容很容易被中间人窃取、伪造和篡改,通常我们把这种攻击方式称为中间人攻击

具体来讲,在将 HTTP 数据提交给 TCP 层之后,数据会经过用户电脑、WiFi 路由器、运营商和目标服务器,在这中间的每个环节中,数据都有可能被窃取或篡改,无法确保数据的保密性(Privacy)、完整性(Integrity)和真实性(Identification)。比如用户电脑被黑客安装了恶意软件,那么恶意软件就能抓取和篡改所发出的 HTTP 请求的内容。或者用户一不小心连接上了 WiFi 钓鱼路由器,那么数据也都能被黑客抓取或篡改。

HTTPS 应运而生

HTTP 的明文传输使得传输过程毫无安全性可言,已经不能适应现代互联网应用的安全要求。1994 年,Netscape 创建了 SSL 协议的原始规范并逐步发布协议改进版(之后 IETF 接手负责该协议,并将其重命名为传输层安全(TLS)协议)。该协议利用数据加密(Encryption)技术,可确保数据在网络上的传输过程中不会被截取及窃听。所以就有了以下公式:

从网络协议栈层面来看,HTTPS 不是一个新的应用层协议,只是在 TCP 和 HTTP 之间插入一个安全层(应用层部分),所有经过安全层的数据都会被加密或者解密。

通常 HTTP 直接和 TCP 通信,HTTPS 则先和安全层通信,然后安全层再和 TCP 层通信。也就是说 HTTPS 所有的安全核心都在安全层,它不会影响到上面的 HTTP 协议,也不会影响到下面的 TCP/IP。

因此要搞清楚 HTTPS 是如何工作的,就要弄清楚安全层是怎么工作的。

总的来说,安全层有两个主要的职责:对发起 HTTP 请求的数据进行加密操作和对接收到 HTTP 的内容进行解密操作。

总结一下,由于 HTTP 是明文传输,在传输过程中数据是很容易被窃取或篡改的。为了确保传输的安全性,基于加密技术的安全协议(SSL/TLS)出现。在 HTTP 协议传输过程中加入安全层的技术我们就称之为 HTTPS,HTTPS 解决了数据安全问题。

安全层(SSL/TLS) 如何实现加解密

为了更好地理解安全层是如何实现加解密的,接下来,我们就一步一步实现一个从简单到复杂的加解密技术。

第一版:使用对称加密

提到加密,最简单的方式是使用对称加密。所谓对称加密是指加密和解密都使用的是相同的密钥

浏览器和服务器想要加解密同一个数据,它们至少需要知道加解密算法和密钥,因此,在传输目标数据之前,双方需要进行握手协商,来明确采用的加解密方式和秘钥。过程如下所示:

为了让加密的密钥更加难以破解,我们让服务器和客户端同时决定密钥,具体过程如下:

  • 浏览器发送它所支持的加密套件(加密算法)列表和一个随机数 client-random。
  • 服务器会从加密套件列表中选取一个加密套件,然后还会生成一个随机数 service-random,并将 service-random 和加密套件列表返回给浏览器。
  • 最后浏览器和服务器分别返回确认消息。

这样浏览器端和服务器端就协商好了加密算法,同时也拥有两个相同的随机数,它们就可以使用这两个随机数生成一个密钥 master secret,双方就可以进行数据的加密传输了。

在接下来的所有目标数据传输之前,都会先进行加密,从而确保了网络上传输的数据都是经过加密的。

然而,这种加解密技术还是不安全的,密钥的传递是公开的。握手协商过程还是明文传输的,攻击者是可以拿到协商的加密套件和双方的随机数,同时利用随机数合成密钥的算法是公开的,那就意味着攻击者是可以知道双方的加密套件和秘钥,那加密过的数据在攻击者面前也就形同虚设了。

WechatIMG97.jpeg

第二版:使用非对称加密

使用对称加密,最大的问题就是密钥的传递。

1976年,两位美国计算机学家 Whitfield Diffie 和 Martin Hellman,提出了一种崭新构思,可以在不直接传递密钥的情况下,完成解密。这被称为"Diffie-Hellman密钥交换算法"。这个算法启发了其他科学家。人们认识到,加密和解密可以使用不同的规则,只要这两种规则之间存在某种对应关系即可,这样就避免了直接传递密钥。

这种新的加密模式被称为"非对称加密算法"。

  • 非对称加密算法有两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
  • 使用公钥来加密,只能使用私钥来解密。反之,使用私钥来加密,只能使用公钥来解密。

在非对称加密中,公钥加密的信息只有私钥解得开,那么只要私钥不泄漏,通信就是安全的。

非对称加密算法,解决了密钥传递困难的问题。接下来,我们就使用非对称机密来实现第二版的加解密技术。

服务器拥有公钥和私钥,在握手协商阶段,会把公钥发送给浏览器,而私钥只能自己拥有,不能公开。

根据该图,我们来分析下使用非对称加密的请求流程。

  • 首先浏览器还是发送加密套件列表给服务器。
  • 然后服务器会选择一个加密套件,和公钥一起发送给浏览器。
  • 最后就是浏览器和服务器返回确认消息。

这样浏览器就有了服务器的公钥,在浏览器端向服务器端发送数据时,就可以使用该公钥来加密数据。由于公钥加密的数据只有私钥才能解密,所以即便黑客截获了数据和公钥,他也是无法使用公钥来解密数据的。

因此采用非对称加密,看上去似乎很完美,不过这种方式依然存在三个严重的问题。

  1. 非对称加密的效率太低。这会严重影响到加解密数据的速度,进而影响到用户打开页面的速度。
  2. 无法保证服务器发送给浏览器的数据安全。虽然浏览器端可以使用公钥来加密,但是服务器端只能采用私钥来加密,私钥加密只有公钥能解密,但中间人也是可以获取到公钥的,这样就不能保证服务器端数据的安全了。
  3. 无法确保公钥的可靠性。公钥是通过明文发送到浏览器的,如果中间人截获并替换为自己的公钥,那浏览器发送的加密数据中间人就能破解,同时服务端发送的加密数据使用截获的公钥也能破解。

第三版:对称加密和非对称加密搭配使用

对于前两个问题,我们可以在传输数据阶段依然使用对称加密,但是对称加密的密钥我们采用非对称加密来传输。下图就是改造后的版本:

从图中可以看出,改造后的流程是这样的:

  • 首先浏览器向服务器发送对称加密套件列表、非对称加密套件列表和随机数 client-random;
  • 服务器保存随机数 client-random,选择对称加密和非对称加密的套件,然后生成随机数 service-random,向浏览器发送选择的加密套件、service-random 和公钥;
  • 浏览器保存公钥,并生成随机数 pre-master,然后利用公钥对 pre-master 加密,并向服务器发送加密后的数据;
  • 最后服务器拿出自己的私钥,解密出 pre-master 数据,并返回确认消息。

服务器和浏览器使用这三组随机数生成对称密钥,因为服务器和浏览器使用同一套方法来生成密钥,所以最终生成的密钥也是相同的。有了对称加密的密钥之后,双方就可以使用对称加密的方式来传输数据了。因为密钥是使用非对称加密传递的,确保了密钥不会泄漏。

第四版:使用数字证书

我们解决了非对称加密存在的前两个问题,目前还存在一个问题,那就是公钥的可靠性问题。

WechatIMG98.jpeg

中间人在握手协商阶段,可以截获到加密套件以及服务端的公钥。同时也拥有自己的公钥和私钥。当服务器想浏览器发送公钥时,可以从中替换为自己的公钥。这样,浏览器拿到的公钥就是中间人的(浏览器是无法辨别公钥是目标服务器的还是攻击者的),浏览器发的加密数据中间人自然就能解密。中间人篡改数据后,使用服务器的公钥加密,伪装为浏览器,发送给服务器,这时服务器是无法发现异常的。

为了解决公钥的可靠性,需要服务器向浏览器提供证明“我就是我”,那怎么证明呢?

这就需要引入第三方权威机构 CA Certificate Authority ), 服务器需要向这些机构提供相关信息,CA 确认后会向服务器颁发一个数字证书(Digital Certificate) 。其实这个数字证书类似于公钥,但是它能证明“我就是我” 。服务器将数字证书发给浏览器后,浏览器通过数字证书信息可以证明,这个证书是不是目标服务器的。

对于浏览器来说,数字证书有两个作用:数字证书可以证明服务器的身份,另一个是数字证书里面包含了服务器公钥。

接下来我们看看含有数字证书版本的流程图:

相较于第三版,这里主要有两点改变:

  1. 服务器没有直接返回公钥给浏览器,而是返回了数字证书,而公钥正是包含在数字证书中的。
  2. 在浏览器端多了一个证书验证的操作,验证了证书之后,才继续后续流程。

通过引入数字证书,我们就实现了服务器的身份认证功能,这样即便攻击者伪造了服务器,但是由于证书是没有办法伪造的,所以依然无法欺骗用户,确保了公钥的可靠性。

浏览器向服务器发送的消息还是无法保证完整性,因为服务器的公钥是公开的,中间人可以替换掉浏览器向服务器发送的消息。

数字证书 (Digital Certificate)

如何申请数字证书

如果网站需要向 CA 申请数字证书,大致的申请流程如下:

  1. 网站需要准备一套私钥和公钥,然后填写了一张含有自己身份信息的表单,身份信息包括了自己公钥、站点资料、公司资料等信息,然后将其提交给了 CA 。
  2. CA 会通过线上、线下等多种渠道来验证所提供信息的真实性。
  3. CA 对明文资料进行 Hash 计算得出信息摘要, 利用 CA 的私钥加密信息摘要得出数字签名。
  4. CA 向网站签发认证的数字证书,包含了网站的公钥、组织信息、CA 的信息、有效时间、证书序列号等,这些信息都是明文的,同时包含上一步生成的数字签名。

浏览器如何验证数字证书

在安全层握手协商阶段,服务器会向浏览器发送自己的数字证书,而浏览器拿到数字证书的第一件事就是验证数字证书,如果数字证书有效,那么里面的服务器的公钥则也是可靠的。

浏览器需要验证证书的有效期、证书是否被 CA 吊销、证书是否是合法的 CA 机构颁发的。

证书里面包含有效期,浏览器只需要判断当前时间是否在证书的有效期范围内即可。

验证数字证书是否被吊销了。通常有两种方式,一种是下载吊销证书列表 -CRL (Certificate Revocation Lists),第二种是在线验证方式 -OCSP (Online Certificate Status Protocol)。

最重要的是校验数字证书的合法性:

  • 首先,浏览器利用证书的原始信息计算出信息摘要。
  • 然后,利用 CA 的公钥来解密数字证书中的数字签名,解密出来的数据也是信息摘要。
  • 最后,判断这两个信息摘要是否相等就可以了。

上述的流程,需要使用到 CA 的公钥,浏览器是如何获取到可靠的 CA 公钥的呢?

浏览器是怎么获取到 CA 公钥的

通过前面的了解,我们可以明确知道 CA 公钥不能通过网络去获取的,否则就会形成一个死循环。

最终的妥协的方案是,直接在操作系统中内置这些 CA 的数字证书,而证书里就包含了 CA 的公钥。

我们将所有 CA 机构的数字证书都内置在操作系统中,并且默认它们都是合法的。当需要使用某 CA 的公钥时,我们只需要依据 CA 机构名称,就能查询到对应的数字证书并取出公钥。

不过这种方式依然存在一个问题,因为在实际情况下,CA 机构众多,因此操作系统不可能将每家 CA 的数字证书都内置进操作系统,而且更新也不方便。

数字证书链

于是人们又想出来一个折中的方案,将颁发证书的机构划分为两种类型, CA (Root CAs )和中间 CA(Intermediates CAs) ,通常申请者都是向中间 CA 去申请证书的,而根 CA 作用就是给中间 CA 做认证,一个根 CA 会认证很多中间的 CA,而这些中间 CA 又可以去认证其他的中间 CA。

因此,每个根 CA 机构都维护了一个树状结构,一个根 CA 下面包含多个中间 CA,而中间 CA 又可以包含多个中间 CA。这样就形成了一个证书链,你可以沿着证书链从用户证书追溯到根证书。

以下是飞书的数字证书信息,可以看到 .feishu.cn 的证书是由中间 CA RapidSSL RSA CA 2018 颁发的,而中间 CA RapidSSL RSA CA 2018 又是由根 CA DigiCert Global Root CA 颁发的,所以这个证书链就是:.feishu.cn —> RapidSSL RSA CA 2018 –> DigiCert Global Root CA。

这里简单介绍下数字证书的合法性验证流程,以上述飞书数字证书为例:

  • 浏览器拿到飞书的数字证书后,先判断是否为根证书。
  • 如果是根证书,则在本地操作系统内查找该证书,如果找到,就可以使用公钥进行校验;如果没有找到,则为非法数字证书。
  • 如果不是根证书,则会去下载颁发飞书数字证书的 CA 的数字证书(DigiCert Global Root CA)。
  • 如果根数字证书验证通过,则整个数字证书链都是通过的。
  • 重复上述的步骤,直到没有父级证书,则验证失败。

如果攻击者想冒充某个中间数字证书,显然是不可行的,因为它需要冒充数字证书的颁发机构,最后到根证书时,是能验证根证书是否颁发过该证书的。

如何验证根证书的合法性

如果某个机构想要成为根 CA,并让它的根证书内置到操作系统中,那么这个机构首先要通过 WebTrust 国际安全审计认证。

什么是 WebTrust 认证?

WebTrust 是由两大著名注册会计师协会 AICPA(美国注册会计师协会)和 CICA(加拿大注册会计师协会)共同制定的安全审计标准,主要对互联网服务商的系统及业务运作逻辑安全性、保密性等共计七项内容进行近乎严苛的审查和鉴证。 只有通过 WebTrust 国际安全审计认证,根证书才能预装到主流的操作系统,并成为一个可信的认证机构。

目前通过 WebTrust 认证的根 CA 有 Comodo、geotrust、rapidssl、symantec、thawte、digicert 等。也就是说,这些根 CA 机构的根证书都内置在操作系统中,只要能从数字证书链往上追溯到这几个根证书,浏览器就会认为使用者的证书是合法的。

SSL 和 TLS

在讲到 HTTPS 时,很多人会被 SSL 和 TLS 困惑住,这一小节就来简单介绍下这两个概念。

1994 年,Netscape 创建了 SSL(Secure Sockets Layer) 协议,该协议利用数据加密(Encryption)技术,可确保数据在网络上的传输过程中不会被截取及窃听。

SSL 第一个版本从未发布,第二个版本于 1995 年与浏览器 Netscape 1.1 一起发布,同年发布了第三个版本,因为第二版存在一些主要的安全问题。

直到 1999 年,Netscape 和 Microsoft 之间的浏览器战争、对标准的需求等原因,Netscape 将 SSL 协议的控制权交给了 IETF(Internet Engineering Task Force)。

1999 年底,IETF 发布了 TLS 1.0 版(实际上是 SSL 3.1),至此,SSL 被正式更名为 TLS(Transport Layer Security)。SSL 和 TLS 的关系就是:TLS 是 SSL 3.0 以后的版本

以下是 TLS 版本发布时间轴:

然而,直到 2013 年浏览器才开始迎头赶上并添加对 TLS 1.2 的支持。SSL 3.0 在 2015 年被正式弃用(因为 2014 年著名的 Poodle Attack)。

TLS 1.3 于 2018 年 3 月获得批准,带来了巨大的安全改进并删除了旧的较弱的功能。

SSL 是 1994年 Netscape 创建的原始协议,现在已弃用。TLS 是 IETF 维护的网络安全加密的新协议。

非对称加密算法

非对称加密算法有很多种,使用最广泛的是 RSA 算法,接下来就以 RSA 为例,向大家介绍下非对称加密算法背后的原理。

公钥和私钥如何生成

RSA 算法并不难,不过我们需要先储备几个相关的数学知识。

互质关系

如果两个正整数,除了 1 以外,没有其他公因子,我们就称这两个数是互质关系(coprime),比如,15 和 32 没有公因子,所以它们是互质关系。这说明,不是质数也可以构成互质关系。

欧拉函数

欧拉函数 φ(n) 表示在小于等于 n 的正整数(1-n)之中,与 n 构成互质关系的数的个数。比如:在 1 到 8 之中,与 8 形成互质关系的是 1、3、5、7,所以 φ(8) = 4。

如果n是质数,则 φ(n)=n-1 。因为质数与小于它的每一个数,都构成互质关系。比如 5 与 1、2、3、4都构成互质关系。

欧拉函数还存在这样的变形,对于质数 p1 和 p2:φ(n) = φ(p1p2) = φ(p1)φ(p2)

模反元素

如果两个正整数 a 和 n 互质,那么一定可以找到整数b,使得 ab-1 被 n 整除,或者说 ab 被 φ(n) 除的余数是 1。

ab=1 (mod φ(n))ab = 1 \ (mod \ {φ(n)})

这时,b 就叫做 a 的模反元素

接下来,我们就可以生成公钥和私钥了:

  1. 随机选择两个不相等的质数 p 和 q。比如 61 和 53。(越大越难破解)
  2. 取两个质数的乘积:n = 61 × 53 = 3233。
  3. 计算 n 的欧拉函数 φ(n)。根据公式φ(n) = φ(pq) = (p-1)(q-1),得 φ(3233) = 60 × 52 = 3120。
  4. 随机选择一个整数 e,条件是 1 < e < φ(n),且 e 与 φ(n) 互质。比如 17。
  5. 计算 e 对于 φ(n) 的模反元素 d。根据公式ed=1 (mod φ(n))ed = 1 \ (mod \ φ(n))取一个解 d = 2753。
  6. 将 n 和 e 封装成公钥,n 和 d 封装成私钥。该例子中,n=3233,e=17,d=2753,所以公钥就是 (3233, 17),私钥就是(3233, 2753)。

我们随机取了两个质数 p 和 q,取它们的乘积为 n,计算 φ(n),在小于 φ(n) 的正整数中,随机取个数 e,让 e 与 φ(n) 互质,最后我们计算 e 对于 φ(n) 的模反元素 d,就得到了公钥和私钥需要的三个数字:n,e,d。

加密和解密

我们知道非对称算法的私钥和公钥是存在某种关联规则的,这也是为什么公钥和私钥的生成方式如上。

通过上述方式生成的公钥和私钥,他们的关联规则也很简单:

对于需要加密的消息 m,可以使用公钥(n, e)代入以下公式加密,加密后的密文就是 c

加密:me=c (mod n)m^e = c \ (mod \ n)

比如上述例子公钥是(3233, 17),假设加密消息 m 为 65:

651765^{17} % 3233 = = 2790 (mod 3233)。那加密后消息就是 2790。

然后我们可以使用以下解密公式,对密文 c 进行解密,得到 m

解密:cd=m (mod n)c^d = m \ (mod \ n)

279027532790^{2753} % 3233 = = 65 (mod 3233)。那解密后消息就是 65。

我们可以看到,如果不知道 d,就没有办法从 c 求出 m。而要知道 d 就必须分解 n,这是极难做到的,所以 RSA 算法保证了通信安全。

RSA 算法的可靠性

在解密公式中,主要参数是 d,根据求模反公式,需要知道 e 和 φ(n),才能算出 d,而 e,n 是公钥。所以需要根据 n 求出 φ(n)。

n 是两个质数 p 和 q 的乘积,只要知道 p 和 q,φ(n) 就可以根据 φ(n)=(p-1)(q-1) 得到。

所以,只要能对 n 进行因数分数,找到两个质数 p 和 q,那么 RSA 算法就可以被破解。

假如有人能够找到一种有效的分解大整数的算法的话,或者假如量子计算机可行的话,那么在解密和制造更长的钥匙之间就会展开一场竞争。但从原理上来说 RSA 在这种情况下是不可靠的。

对极大整数做因数分解的难度决定了 RSA 算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠。

目前来看,RSA 算法是非常靠谱的,而且密钥越长,它就越难破解。根据已经披露的文献,目前被破解的最长 RSA 密钥是 768 个二进制位。也就是说,长度超过 768 位的密钥,还无法破解(至少没人公开宣布)。因此可以认为,1024 位的 RSA 密钥基本安全,2048 位的密钥极其安全。

HTTPS 是绝对安全的吗

基于以上我们对 HTTPS 的了解,可以发现,HTTPS 可能存在的风险主要有以下两个:

  1. 非对称加密算法的破解。
  2. 本地系统被安装了非法的根证书。

对于第一点,前面已经介绍了,目前 RSA 算法是非常靠谱的,秘钥越长破解难度越大。

对于第二点,我们不要安装不受信任的数字证书。 我们可以查看系统本地的根证书,是否存在不受信任的,及时清理掉。

HTTPS 性能影响

在 HTTPS 传输数据之前,需要先进行安全层(SSL/TLS)的握手协商,相对于 HTTP,显然是增加了一定的耗时,增加延时 2 RTT。

另外数据的加解密也会增加耗时,并增加 CPU 消耗,RSA 的解密能力是当前 HTTPS 主要性能消耗。

参考资料