2020 / 01 / 18
by John Yuan

HTTPS 基本加密流程简述

HTTP 协议可以说是目前互联网应用程序中使用最为广泛的协议。HTTPS(即 HTTP Over TLS)通过在 HTTP 协议之下添加一层 TLS 协议,以确保数据在一个加密的信道中传输,从而增加安全性能。本文简单描述了我们认为 HTTP 不安全的原因,以及 HTTPS 的基本加密流程。

本文从一个较为宽泛的角度回答了文章开头所提出的问题,如需了解具体细节,请参考文章结尾处给出的参考资料。

1. 为什么 HTTP 不安全?

由于 HTTP 是以明文的形式进行数据传输的,从客户端到服务器可能会经过多个中间节点(如 WiFi 热点、路由器、反向代理、网络运营商节点等),因此存在以下问题:

  1. 中间人(Man-in-the-Middle)可以看到 HTTP 传输的内容:比如用户在搜索引擎中输入的某个关键字,或者用户用来进行登录的用户名和密码,这些信息都会被中间人看到。
  2. 内容可能被篡改:由于内容是明文传输,中间人不仅可以看到传输的具体数据,还可以对这些数据进行修改。比如在服务器返回的 HTML 中插入一段 JavaScript 脚本以植入广告等。

当然,除了上面所描述的问题以外,也许还存在其他方面的问题。不过上面的两个问题应该足以说明 HTTP 是不安全的。

2. HTTPS 是怎么确保安全的?

HTTPS 在 HTTP 协议下添加了一层 TLS 协议。每次数据传输前都会进行 TLS 握手,TLS 握手完成后,便建立了一个加密的通道,后续所有的应用数据传输都将在这个加密通道中进行,从而确保了数据的安全。HTTPS 具有如下特点:

  • 身份验证(Authentication):身份验证是每个 TLS 连接必不可少的部分,用于确保与我们进行数据传输的计算机是可信任的。
  • 机密性(Confidentiality):被传输的数据是经过加密的,并且只有通信的双方知道该如何解密。
  • 数据的完整性(Integrity):被传输的数据虽然是经过加密的,但是中间人仍然可以对加密后的数据进行篡改,从而导致数据的接收方无法正常解密。TLS 提供一种机制来检查数据是否被篡改,原理类似于我们通过对比文件的哈希值来检查我们从网络上下载的文件是否被篡改。

那么 HTTPS 是如何进行数据加密的呢?她采用来哪种形式的加密算法(对称加密还是非对称加密)?我们将在后文进行简述。

3. HTTPS 基本加密流程

在正式描述 HTTPS 加密流程之前,我们需要先了解两种加密形式(即对称加密和非对称加密)各自的特点。

  • 对称加密:对称加密使用同一个密钥进行数据的加密和解密,这就要求通信的双方使用同一个密钥。由此带来的问题是,通信双方必须通过网络共享密钥,而密钥的传输是没有加密的,因此密钥也有可能被中间人截取。密钥被截取后,中间人也可以通过这个密钥来解密同一个密钥加密的数据,从而让加密操作失去了意义。虽然存在这样的缺点,不过对于非对称加密而言,对称加密所需的计算量要小的多,因此性能比非对称加密要更好。
  • 非对称加密:非对称加密使用两个密钥,一个叫做私玥,另一个叫做公钥。使用公钥进行加密的数据,只有用与这个公钥配对的私玥才能解密。服务端生成公钥私钥后,将公钥通过网络传输给客户端,客户端用这个公钥来加密需要传输的数据并发送给服务端,服务端用私玥解密即可查看原始数据。即使中间人截取了公钥和被加密的数据,由于没有私玥,他也无法解密。虽然非对称加密非常安全,但是对比对称加密而言需要更大的计算工作量,因此更占用计算机 CPU 资源,如果有大量的 TLS 连接,显然会导致性能问题。

那我们该用对称加密还是非对称加密呢?答案是两种加密方式都会用到。TLS 在握手阶段会协商出一个用于对称加密的密钥,具体流程是:服务端将自己的非对称加密密钥对中的公钥发送给客户端,客户端生成一个用于对称加密的密钥,然后用服务端提供的公钥加密这个密钥并发送给服务端,发送完成后,客户端和服务端都拥有了同一个用于对称加密的密钥,后续发送的应用数据都会用这个密钥进行加密和解密。由于密钥的传输是经过非对称加密的,所以中间人无法截取到此密钥。

由于每一次连接都会进行 TLS 握手,也就是说每一次连接都会用到非对称加密和对称加密,因此由非对称加密带来的性能问题依然存在。不过好在 TLS 提供了一种会话缓存机制(类似于 Web 应用中的 Session 机制),使得我们可以重复利用第一次握手操作中协商出来的对称加密密钥,后续的连接可以继续使用这个对称加密密钥而不必重新生成,因此在后续连接的 TLS 握手操作中可以省去非对称加密和生成对称加密密钥的流程,从而提升了性能。这也是为什么大多数现代浏览器在发送多个 HTTPS 请求时,往往会有意等待第一个 TLS 连接完成后才会发送后续的 HTTPS 请求的原因。目的是为了利用第一个 HTTPS 请求协商出来对称加密密钥,避免重新生成密钥带来的性能损失。

4. 参考资料

本文完。