一. 什么是 HTTPS

HTTP 由于是明文传输,所谓的明文,就是说客户端与服务端通信的信息都是肉眼可见的,随意使用一个抓包工具都可以截获通信的内容。

所以安全上存在以下三个风险:

  • 窃听风险,比如通信链路上可以获取通信内容,用户号容易没。
  • 篡改风险,比如强制植入垃圾广告,视觉污染,用户眼容易瞎。
  • 冒充风险,比如冒充淘宝网站,用户钱容易没。

HTTPS 在 HTTP 与 TCP 层之间加入了 TLS 协议,来解决上述的风险。

img

二. HTTPS 加密流程

HTTPS 主要是通过在 HTTP 协议基础上加入 SSL/TLS 协议来实现加密,HTTPS 是应用层协议,需要先建立 TCP 连接,并完成 TLS 握手后,才能建立通信安全的连接。其加密过程分为对称加密和非对称加密两个阶段。非对称加密阶段主要目的是为了交换对称加密密钥,我们也称之为 TLS 协议握手,TLS 握手成功后,就会使用对称机密的方式进行加密传输。

在非对称加密阶段,服务器拥有一对公钥和私钥(非对称加密特性:公钥加密的数据只有私钥能解密,私钥加密的数据只有公钥能解密)。服务器将公钥发送给客户端,客户端使用公钥对一个随机生成的对称密钥进行加密,并将加密后的对称密钥发送回服务器。由于只有服务器拥有私钥,所以只有服务器能够解密得到对称密钥,服务端获取到对称加密密钥后我们即可认为 TLS 握手成功。

一旦TLS握手成功建立,双方(客户端与服务器)将使用之前协商好的对称密钥进入对称加解密阶段。

可以想象的是,整个过程中最重要的一步是客户端如何安全的获取到非对称加密公钥;这一步的安全性直接关系到了之后对称密钥交换的安全性。我们可以设想如下情景:

img

当客户端尝试通过公网去服务器获取公钥时,被网络中间节点识别到此次请求是获取公钥的请求后,代替客户端向服务器获取一个公钥,但是此时中间节点并不把获取到的真实的服务器公钥返回给客户端,而是自己生成了一对非对称密钥,然后将自己生成的公钥返回给客户端,客户端拿到的并不是目标服务器提供的公钥。此时客户端生成对称密钥后使用假公钥进行加密,然后将对称密钥发送给服务端,网络中间节点获取到这个请求后就能用自己的私钥进行解密,中间人一旦获取到对称密钥后续的网络通信对这个中间人就没有任何秘密可言了。

实际上,TLS 协议的握手过程并非固定不变,它会依据所采用的密钥交换算法的不同而产生变化。在 HTTPS 通信场景中,常见的密钥交换算法有 RSA 和 ECDHE 等。在此过程中,关键在于要明白,在 TLS 握手阶段,主要是借助非对称加密算法的独特性质,来安全地实现对称加密密钥的交换。接下来,我们会以 RSA 非对称加密算法的密钥交换流程为例,对 HTTPS 的加密机制展开详细介绍。这种介绍将有助于我们深入理解在网络通信中,数据是如何在安全保障下进行传输的,同时也能让我们清晰地看到不同加密算法在整个加密机制中所扮演的重要角色。

RSA 实际上是比较传统的密钥交换算法,它并不具备前向安全的性质(一旦对称加密服务端私钥被破解 or 盗取,攻击者就可以利用这个私钥去解密过去所有使用该私钥相关加密信息生成的会话密钥加密的通信内容)。因此现在很少服务器使用。而 ECDHE 算法具有前向安全,所以被广泛使用,ECDHE 算法涉及到椭圆曲线密码学,理解成本比较高,有兴趣的同学可以自行了解。

什么是椭圆曲线密码学? - Keeper Security

本文旨在阐述 HTTPS 的核心思想:混合加密流程(利用非对称加密安全地交换对称密钥,然后进行对称加密传输)

三. 如何保证公钥获取安全性

这主要是通过数字证书来实现的。服务器的公钥并不是直接发送给客户端,而是包含在数字证书中。数字证书是由权威的证书颁发机构(CA)颁发的,它就像是网络世界中的 “身份证”。

例如,如果我们需要给一个 Nginx 配置证书,我们需要在 nginx 配置文件中指定证书和私钥文件的位置:

1
2
3
4
5
6
7
8
server {
listen 443 ssl;
# 指定 ssl 证书路径
ssl_certificate /ssl/blog.bigcoder.cn_nginx/blog.bigcoder.cn_bundle.crt;
# 指定私钥文件路径
ssl_certificate_key /ssl/blog.bigcoder.cn_nginx/blog.bigcoder.cn.key;
server_name ~^blog\.(bigcoder)\.cn$;
}

这样一个新的 https 连接进入 Nginx 时,服务器会将配置的证书发送给客户端,客户端使用的证书中的公钥进行对称密钥的加密交换。

在获取证书过程中同样需要保证安全性,这里的安全性有几个方面:

  1. 证书不能被第三方伪造:如果证书能够随意伪造,那么网络攻击者可以使用伪造的网站证书冒充任意网站与客户端进行网络传输,中间人从而可以从中轻易的窃听、篡改网络数据。

  1. 证书内容不会被篡改:证书如果能够被篡改,客户端向网站服务器获取证书时,中间人可以劫持此次请求,将证书中的公钥信息替换成自己的公钥发送给客户端,此时后续的密钥交换流程也就没有任何安全可言了。

四. HTTPS 证书内容

通过 openssl命令可以查看证书的内容,例如我们查看 blog.bigcoder.cn证书的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
$ openssl x509 -in blog.bigcoder.cn_bundle.crt -noout -text
Certificate:
Data:
Version: 3 (0x2) #表示这是 X.509 证书的版本 3。
Serial Number: #序列号:用于唯一标识该证书。
68:41:e9:13:6d:3f:75:9c:bd:86:35:05:e0:55:76:47
Signature Algorithm: sha384WithRSAEncryption #签名算法:sha1WithRSAEncryption,表明使用 SHA-1 哈希算法和 RSA 加密算法进行签名。
Issuer: C=CN, O=TrustAsia Technologies, Inc., CN=TrustAsia RSA DV TLS CA G2 #CN = ACCVRAIZ1, OU = PKIACCV, O = ACCV, C = ES,即证书的颁发机构信息,包括通用名称(CN)、组织单位(OU)、组织(O)和国家(C)。
Validity #有效期
Not Before: Feb 10 00:00:00 2023 GMT
Not After : Feb 10 23:59:59 2024 GMT
Subject: CN=blog.bigcoder.cn #与颁发者信息相同,CN = ACCVRAIZ1, OU = PKIACCV, O = ACCV, C = ES,代表证书的所有者。
Subject Public Key Info:
Public Key Algorithm: rsaEncryption #公钥算法:rsaEncryption,使用 RSA 非对称加密算法。
Public-Key: (2048 bit) #公钥
Modulus:
00:bb:68:7c:38:30:e9:0e:68:a0:2b:76:a3:28:d4:
77:6c:8a:8b:1a:79:2e:49:1f:77:47:56:a7:dd:8c:
6c:e6:d2:32:bf:8d:84:e5:a9:7f:6a:81:89:ea:92:
9e:60:35:13:58:47:48:61:3b:43:21:a6:e9:ca:8c:
a4:4f:93:c2:ef:dc:d3:71:07:ea:c8:78:20:ff:1d:
d0:c7:d7:75:5f:e8:3a:ab:55:da:cc:22:14:d9:a4:
2e:99:fc:76:0e:da:a7:66:bc:19:9f:75:54:2c:c2:
f1:9e:4f:3a:5c:6e:37:99:8b:96:16:d3:87:1a:eb:
48:99:db:07:7c:f5:1f:b6:d4:e2:2f:b3:b6:d7:0e:
0c:83:bb:21:29:64:61:96:b5:a0:94:1b:f1:af:7c:
ad:4c:30:4a:eb:43:f7:d6:e4:ff:30:cb:1f:91:e4:
61:8f:f9:52:7c:07:3a:0a:9c:b8:9d:35:28:93:8c:
0d:82:72:06:b9:51:ce:71:b6:18:05:e4:ec:b7:15:
4d:19:76:d7:51:2f:07:53:37:dc:1b:45:59:43:99:
c2:df:a8:c3:0d:62:eb:bd:1a:05:48:bb:cc:a2:af:
2e:d9:a2:a6:91:c3:2a:52:86:01:6c:e9:0e:d6:f9:
24:b6:0c:e7:3c:77:eb:2b:4c:fd:d6:a4:aa:24:ef:
9e:fb
Exponent: 65537 (0x10001)
.....
Signature Algorithm: sha384WithRSAEncryption
Signature Value: #证书签名
1c:ed:69:a2:43:38:c6:fa:b0:9d:4c:4c:77:ff:5c:f8:f8:fd:
b5:9a:3d:2d:e9:89:43:97:aa:92:67:e8:1a:a6:fe:d4:40:cc:
a7:34:de:09:70:7a:0e:70:56:77:e1:d0:d1:91:01:86:10:1f:
0b:64:b7:b5:98:60:c7:55:68:fd:23:a9:86:6a:d8:3f:29:de:
dd:d4:e3:d5:02:96:78:a8:ec:e5:b1:32:2e:59:b7:12:e2:72:
08:39:7f:aa:75:f0:b9:6e:02:94:55:38:71:87:6c:e3:d6:1c:
66:a4:ad:64:23:fa:6d:c6:bc:29:96:70:a4:92:80:5d:eb:e2:
2d:c0:27:28:54:40:af:e5:4f:31:19:ce:cc:75:1d:3d:29:6d:
29:5a:2b:de:ad:54:db:fb:bd:8a:15:a2:46:61:dd:7e:da:a8:
ba:b0:26:ce:18:6d:43:da:f7:20:5e:75:79:5d:dc:f7:59:af:
47:9c:b8:79:6d:f9:df:17:ef:d0:0f:49:db:a5:34:40:4d:15:
cd:22:d8:0e:be:89:06:40:6d:40:15:a6:53:f3:6e:37:35:ea:
37:28:bd:18:68:b2:67:f2:c3:73:96:27:9a:d3:a4:2d:d3:8a:
57:9d:b1:a8:3a:03:b8:2f:b0:e7:88:52:15:19:fd:a4:4b:3f:
59:ea:a8:47:e8:98:a5:e2:75:5b:1f:4c:79:b2:dd:d4:e3:90:
1e:f2:fc:d9:f4:2c:0b:ba:dd:e6:57:3d:5b:42:e4:a3:de:b4:
85:98:ea:73:3e:0e:67:61:0b:68:75:69:5a:1f:fc:ba:8c:f2:
0f:4b:42:7b:b1:60:d6:d6:09:a3:53:c6:70:f5:84:90:d3:72:
aa:f5:af:1f:dc:7c:78:94:ac:68:bb:4a:bc:4f:29:a2:73:a0:
90:06:b2:0a:8b:3e:71:36:1a:96:e5:ec:45:2a:46:db:4f:df:
8f:99:d5:4e:e2:45:06:93:2d:a2:e9:ec:c1:15:ff:f8:b0:85:
ac:47:4d:9c:60:98

一、证书基本信息

  1. 版本:Version 3,表示这是 X.509 证书的版本 3。
  2. 序列号:6828503384748696800,用于唯一标识该证书。
  3. 签名算法:sha1WithRSAEncryption,表明使用 SHA-1 哈希算法和 RSA 加密算法进行签名。
  4. 颁发者:CN = ACCVRAIZ1, OU = PKIACCV, O = ACCV, C = ES,即证书的颁发机构信息,包括通用名称(CN)、组织单位(OU)、组织(O)和国家(C)。
  5. 有效期
    • Not Before:2011 年 5 月 5 日 09:37:37 GMT,证书开始生效的时间。
    • Not After:2030 年 12 月 31 日 09:37:37 GMT,证书过期的时间。

二、主体信息

与颁发者信息相同,CN = ACCVRAIZ1, OU = PKIACCV, O = ACCV, C = ES,代表证书的所有者。

三、主体公钥信息

  1. 公钥算法:rsaEncryption,使用 RSA 非对称加密算法。
  2. RSA 公钥
    • 模数(Modulus):一个 4096 位的大整数,用于 RSA 加密和解密过程中的数学运算。
    • 指数(Exponent):65537,通常在 RSA 算法中是一个固定的标准值。

四、 证书的数字签名

五. 如何保证证书不会被篡改

证书颁发机构(CA)持有非对称加密所需的私钥与公钥。CA 会针对证书的明文信息(涵盖网站域名、证书持有者、有效期、证书自身的公钥以及签名时所运用的哈希算法等要素)实施哈希运算,进而获取一个哈希值。随后,利用自身的私钥对该哈希值予以加密处理,以此生成数字签名。这个数字签名会与证书的明文信息共同组合成完整的证书,并颁发给服务器。

img

鉴于数字签名是经由证书颁发机构的私钥加密生成的,理论上说,客户端能够借助证书颁发机构的公钥对证书的数字签名进行解密操作,得到证书内容的 Hash 值。如此一来,客户端将采用与证书生成时相同的哈希算法对证书内容进行计算,从而得出一个本地的哈希值。对比本地 Hash 值和解密出来的 Hash 值是否相同,客户端便能够知晓证书的内容是否遭到篡改。

img

即便是在 TSL 握手过程中,中间人成功截获了证书数据,然而由于其并不掌握证书颁发者的私钥,因而无法自行计算数字签名。所以,一旦中间人对证书内容进行了修改,那么在客户端进行验证的过程中,就必然会察觉到不一致的情况。

可能有些同学会好奇,为什么不直接用 CA 证书私钥加密证书的所有内容,这样浏览器拿到证书密文后使用公钥解密即可,也就不需要多一步验证 Hash 值的动作。这主要是从性能上做出的妥协,因为非对称加密的性能和原文长度之间不是简单的线性关系。由于加密算法的复杂性,随着原文长度的增长,性能下降的速度可能会加快。所以对证书内容签名后加密既能起到防篡改的目的,还能降低加解密的原文长度,提升性能。

六. 如何保证证书不是第三方伪造

前面说到浏览器会通过网站证书颁发者的公钥解密数字签名后验证证书有效性,那么证书颁发者的公钥又是从哪来的呢?

通常,当你部署 HTTP 服务器的时候,除了部署当前网站的数字证书,还需要部署 CA 机构的数字证书,CA 机构的数字证书包括了 CA 的公钥,以及 CA 机构的一些基础信息。如果有些服务器没有部署 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。这样就形成了一个证书链,你可以沿着证书链从用户证书追溯到根证书。

例如我们以听到微笑的博客为例,访问该网站时可以发现浏览器左上角的安全锁,进去之后我们就能看到其证书的验证的链:

img

6.1 如何验证根证书的合法性

其实浏览器的判断策略很简单,它只是简单地判断这个根证书在不在操作系统里面,如果在,那么浏览器就认为这个根证书是合法的,如果不在,那么就是非法的。

已 MAC 系统为例,在其钥匙串应用中可以看到系统信任的所有根证书:

img

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

什么是 WebTrust 认证?

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

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

6.2 根 CA 证书私钥安全性问题

你可能和我有同样的疑问,根证书既然是采用内置的方式取得系统信任,那么也就证明其证书不会经常变动,那么非法用户能否采用爆破的方式破解根证书私钥后自行颁发非合法的证书呢?

根 CA 证书私钥理论上存在被爆破的可能性,但在实际中极其困难且几乎不可能。以下是具体分析:

  1. 私钥的安全性保障
    • 加密算法强度:根 CA 证书使用的非对称加密算法(如 RSA 等)具有很高的安全性。以常用的 RSA 算法为例,密钥长度足够长时,目前的计算能力难以在合理时间内通过暴力破解的方式获取私钥。例如 2048 位及以上长度的 RSA 密钥,其密钥空间非常大,通过暴力枚举所有可能的密钥组合来破解几乎是不现实的。
    • 密钥的妥善保管:CA 机构对根 CA 证书私钥的保管有极其严格的安全措施和流程,包括物理安全、网络安全、访问控制等多方面的保障。私钥通常存储在高度安全的硬件加密模块(HSM)中,或者采用多重加密、分布式存储等方式,大大降低了私钥被窃取或泄露的风险。
  1. 爆破的巨大难度和时间成本
    • 假设存在一种极端情况,攻击者试图通过暴力破解的方式获取根 CA 证书私钥。如果使用当前最先进的超级计算机,对于一个 2048 位的 RSA 密钥,以每秒尝试数亿亿次的计算速度来计算,所需的时间也是极其漫长的,可能需要数百年甚至更长时间。而且随着密钥长度的增加,破解所需的时间呈指数级增长。所以从实际的时间成本和计算资源需求来看,爆破根 CA 证书私钥是几乎不可行的。

七. 抓包工具为啥能抓取 HTTPS 明文数据

很多抓包工具之所以可以明文看到 HTTPS 数据,工作原理与中间人一致的。

对于 HTTPS 连接来说,中间人要满足以下两点,才能实现真正的明文代理:

  1. 中间人,作为客户端与真实服务端建立连接这一步不会有问题,因为服务端不会校验客户端的身份;
  2. 中间人,作为服务端与真实客户端建立连接,这里会有客户端信任服务端的问题,也就是服务端必须有对应域名的私钥;

中间人要拿到私钥只能通过如下方式:

  1. 去网站服务端拿到私钥;
  2. 去CA处拿域名签发私钥;
  3. 自己签发证书,并且要被浏览器信任;

不用解释,抓包工具只能使用第三种方式取得中间人的身份。

使用抓包工具进行 HTTPS 抓包的时候,需要在客户端安装 Fiddler 的根证书,这里实际上起认证中心(CA)的作用。

抓包工具能够抓包的关键是客户端会往系统受信任的根证书列表中导入抓包工具生成的证书,而这个证书会被浏览器信任,也就是抓包工具给自己创建了一个认证中心 CA,客户端拿着中间人签发的证书去中间人自己的 CA 去认证,当然认为这个证书是有效的。

八. 为什么不直接使用非对称加密加密数据

你或许会思考,既然非对称加密能够确保密钥传输的安全性,那为何不直接运用非对称加密来进行数据的加密传输,而是要先通过非对称加密交换对称密钥,之后再利用对称加密传输数据呢?

这主要是基于性能方面所做出的权衡。原因在于非对称加密的性能与原文长度并非简单的线性关联。鉴于加密算法的复杂性,随着原文长度的增加,其性能下降的速率会愈发加快。故而在使用非对称加密交换固定长度的对称密钥后,后续 HTTPS 的加密性能才能得到有效保障。如此一来,既兼顾了密钥传输的安全性,又在一定程度上保障了加密传输过程中的性能表现,使得整个加密传输体系更为合理和高效。这种方式是在安全性与性能之间寻找到的一种较为平衡的解决方案,以满足实际应用中的多种需求。

参考文章:

网络篇 - https协议中的数据是否需要二次加密_国密改造htpps传参还要加密-CSDN博客

SSL/TLS协议运行机制的概述 - 阮一峰的网络日志

3.1 HTTP 常见面试题 | 小林coding

Charles抓包原理写这篇文章的原因是使用Charles抓包步骤较为繁琐,上手成本不低,容易遗漏某些步骤,导致抓包失败 - 掘金

加餐六|HTTPS:浏览器如何验证数字证书? - 极客时间已完结课程限时免费阅读

36 | HTTPS:让数据传输更安全 - 极客时间已完结课程限时免费阅读

破解 SSL:为什么加密无法破解 - SSL Dragon

细说 CA 和证书 | 小胡子哥的个人网站

3.3 HTTPS RSA 握手解析 | 小林coding

3.1 HTTP 常见面试题 | 小林coding

什么是椭圆曲线密码学? - Keeper Security