
HTTPS 是什么
HTTPS 也是一个应用层协议,是在 HTTP 协议的基础上引入了一个加密层。
HTTP 协议内容都是按照文本的方式明文传输的,这就导致在传输过程中出现一些被篡改的情况。
目前我们已经完成了 HTTP 协议的学习,本篇开启 HTTPS 协议的加餐内容,本篇的核心重点是HTTPS 的握手流程与密钥协商过程,这也是学习 HTTPS 最关键的知识点。
在之前我们了解到,HTTP 与 TCP 连接在通信时,数据都是以明文形式 传输的,无论使用 GET 还是 POST 请求方法,未加密的网络通信都存在极大安全隐患,只有经过加密处理的数据传输,才能保障通信过程的安全性。HTTPS 正是基于 HTTP 构建的安全超文本传输协议,是 HTTP 的加密升级版本。
本篇的内容覆盖会很全面,首先会讲解 HTTPS 的基本概念,以及它和 HTTP 的关联与区别;接着会明确加密、解密、密钥 的核心定义,让大家先建立基础认知;同时会说明明文传输会引发的安全问题,让大家理解加密的必要性。之后会重点讲解两类核心加密算法 ------对称加密 和非对称加密 ,还会配套讲解数据指纹、数据摘要、数字签名这些配套概念,完成基础概念储备后,我们会用自主提出方案→发现缺陷→否定方案→修正优化的思路,逐步推导 HTTPS 的完整实现逻辑,后续还会涉及 CA 机构与数字证书的相关知识。
首先来理解 HTTPS 协议: HTTP 和 HTTPS 都属于应用层协议 ,作用都是完成超文本传输。在网络协议栈中,应用层之下是传输层(TCP/UDP)、网络层(IP)、数据链路层。传统 HTTP 是直接从应用层到传输层完成数据封包传输,而 HTTPS 是在应用层 HTTP 协议之下、传输层之上 ,新增了一层安全加密层 ,这一层就是 TLS/SSL 安全套接字层,同样归属于应用层,由安全工程师负责开发,核心功能是对传输数据做加密、解密以及密钥协商。简单来说,HTTPS 本质就是 HTTP + TLS/SSL,是经过加密解密处理的 HTTP,对上层应用层来说,数据交互的逻辑没有变化,但从传输层开始到网络传输的全流程,数据都是加密安全的。
概念准备
1. 什么是 "加密"
我们原本能直接识别的数据叫做明文 (比如密码 123456),经过加密处理后变成无法直接识别的内容就是密文 ;
加密就是把明文 (要传输的信息)进行一系列变换,生成密文 。解密就是把密文 再进行一系列变换,还原成明文 。
在这个加密和解密的过程中,往往需要一个或者多个中间的数据,辅助进行这个过程,这样的数据称为密钥 (标准读音为 yuè,日常习惯读作 yào)。
加密解密并非计算机专属技术,早在古代就有应用,比如 83 版《火烧圆明园》中,恭亲王奕䜣给慈禧的奏折,表面是家常内容,套上带孔的纸张才能看到真实信息,这里奏折全文是密文,真实信息是明文,带孔的纸就是密钥。

-
明文:
当心肃顺, 端华, 戴恒(这几个人都是当时的权臣,后来被慈禧一锅端)。 -
**密文:**奏折全文
-
**密钥:**挖了洞的纸。

如今加密解密已发展为独立的密码学 ,该学科的奠基人是计算机科学祖师爷之一阿兰・图灵,另一位硬件领域祖师爷是冯・诺依曼,密码学本质上更属于数学范畴。
2. 为什么要加密
互联网早期,百度、阿里、腾讯等大厂的部分产品曾使用明文 HTTP 传输,数据相当于在网络中 "裸奔",最典型的安全问题就是运营商劫持。
早年下载天天动听音乐播放器时,用户点击下载按钮,本应获取天天动听的官方下载链接,却被运营商篡改为 QQ 浏览器的下载链接,最终下载到错误的应用。这是因为所有网络流量都必须经过运营商的路由器、交换机等设备,HTTP 明文传输会让运营商直接看到数据内容,进而随意篡改。


点击 "下载按钮",其实就是在给服务器发送了一个 HTTP 请求,获取到的 HTTP 响应其实就包含了该 APP 的下载链接。运营商劫持之后,就发现这个请求是要下载天天动听,那么就自动的把交给用户的响应给篡改成 "QQ 浏览器" 的下载地址了。

所以:因为http的内容是明文传输的,明文数据会经过路由器、wifi 热点、通信服务运营商、代理服务器等多个物理节点,如果信息在传输过程中被劫持,传输的内容就完全暴露了。劫持者还可以篡改传输的信息且不被双方察觉,这就是中间人攻击,所以我们才需要对信息进行加密。
除了运营商,黑客、恶意 WiFi 热点、代理服务器都可能成为中间人,窃取隐私、篡改信息,尤其在移动支付、转账等场景下,明文传输会引发严重的金融安全问题,因此数据加密的需求迫在眉睫。
试想一下,如果黑客在用户登陆支付宝的时候获取到用户账户余额,甚至获取到用户的支付密码...... 在互联网上,明文传输是比较危险的事情!!!
HTTPS 就是在 HTTP 的基础上进行了加密,进一步的来保证用户的信息安全~
3. 常见的加密方式
最后补充两个关键概念:数据摘要(数据指纹) 和数字签名 。数据摘要是通过单向散列(Hash)函数,对任意长度的数据运算,生成固定长度 的字符串,常见算法有 MD5、SHA1、SHA256 等。它的核心特点是:原始数据哪怕只修改一个比特位,生成的摘要都会发生巨大变化;数据未篡改时,相同算法生成的摘要完全一致,因此摘要不是加密(无解密过程) ,主要用于校验数据是否被篡改 、判断文件是否相同 。比如百度网盘的 "秒传" 功能,就是通过对比文件摘要实现的;用户登录时,数据库也不会保存明文密码,而是保存密码摘要,登录时对比摘要完成身份验证,避免隐私泄露。而数字签名,就是对数据摘要进行加密后的结果,主要用于保障摘要的安全性,这部分内容会在讲解 HTTPS 证书时详细说明。
目前我们已经完成了 HTTPS 相关的基础概念储备,后续我们会基于这些知识,逐步提出并优化 HTTPS 的加密方案,最终推导出完整的安全通信逻辑。现在我们先休息一下,接下来继续讲解 HTTPS 的五种加密方案推导过程。
对称加密
采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密 ,这种加密方法称为对称加密,也称为单密钥加密,特征:加密和解密所用的密钥是相同的。
-
常见对称加密算法(了解):
DES、3DES、AES、TDEA、Blowfish、RC2等 -
特点: 算法公开、计算量小、加密速度快、加密效率高
对称加密其实就是通过同一个 "密钥",把明文加密成密文,并且也能把密文解密成明文。
一个简单的对称加密,按位异或:假设:

明文a=1234,密钥key = 8888
则加密 a ^ key 得到的密文b为9834。然后针对密文9834再次进行运算 b ^ key,得到的就是原来的明文1234。
(对于字符串的对称加密也是同理,每一个字符都可以表示成一个数字)当然,按位异或只是最简单的对称加密。HTTPS 中并不是使用按位异或。
非对称加密
需要两个密钥 来进行加密和解密,这两个密钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。
公钥可以公开传播,泄露也不影响安全;私钥必须由持有者妥善保管,绝对不能泄露。加密解密规则为:公钥加密只能用私钥解密,私钥加密只能用公钥解密,无法用同一密钥完成加解密。
-
常见非对称加密算法(了解):
RSA、DSA、ECDSA -
特点: 算法强度复杂、安全性依赖于算法与密钥,但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。
非对称加密要用到两个密钥,一个叫做 "公钥",一个叫做 "私钥"。公钥和私钥是配对的。最大的缺点就是运算速度非常慢,比对称加密要慢很多。
-
通过公钥对明文加密,变成密文
-
通过私钥对密文解密,变成明文也可以反着用
-
通过私钥对明文加密,变成密文
-
通过公钥对密文解密,变成明文

非对称加密的数学原理比较复杂,涉及到一些数论相关的知识。这里举一个简单的生活上的例子:A 要给 B 一些重要的文件,但是 B 可能不在。于是 A 和 B 提前做出约定:B 说:我桌子上有个盒子,然后我给你一把锁,你把文件放盒子里用锁锁上,然后我回头拿着钥匙来开锁取文件。在这个场景中,这把锁就相当于公钥,钥匙就是私钥。公钥给谁都行(不怕泄露),但是私钥只有 B 自己持有。持有私钥的人才能解密。
4. 数据摘要 && 数据指纹
数字指纹(数据摘要) ,其基本原理是利用单向散列函数(Hash 函数) 对信息进行运算,生成一串固定长度的数字摘要。数字摘要/指纹并不是一种加密机制,但可以用来判断数据有没有被篡改。
-
摘要常见算法:
MD5、SHA1、SHA256、SHA512等,算法把无限的映射成有限,因此可能会有碰撞(两个不同的信息,算出的摘要相同,但是概率非常低) -
摘要特征 :和加密算法的区别是,摘要严格意义不是加密,因为没有解密,只不过从摘要很难反推原信息,通常用来进行数据对比
核心特点是: 原始数据哪怕只修改一个比特位,生成的摘要都会发生巨大变化;数据未篡改时,相同算法生成的摘要完全一致,因此摘要不是加密(无解密过程) ,主要用于校验数据是否被篡改 、判断文件是否相同。

比如百度网盘的 "秒传" 功能,就是通过对比文件摘要实现的;用户登录时,数据库也不会保存明文密码,而是保存密码摘要,登录时对比摘要完成身份验证,避免隐私泄露。
cpp
【用户本地文件】
↓
【本地计算文件完整哈希摘要(MD5/SHA)】
↓
【仅把 摘要字符串 发送给百度网盘服务器】
↓
服务器比对:数据库中是否已存在相同摘要?
├─✅ 存在相同摘要(别人/自己传过同款文件)
│ ↓
│ 【服务器直接调取已有文件资源】
│ ↓
│ 【绑定到你的网盘账户 → 秒传完成】
│
└─❌ 无匹配摘要(全新文件)
↓
【完整上传文件数据】
↓
【服务器保存文件 + 记录该文件摘要】
5. 数字签名
数字签名,就是对数据摘要进行加密后的结果,主要用于保障摘要的安全性,这部分内容会在讲解 HTTPS 证书时详细说明。
6. 理解链 - 承上启下
-
对
http进行对称加密,是否能解决数据通信安全的问题?问题是什么? -
为何要用非对称加密?为何不全用非对称加密?
目前我们已经完成了 HTTPS 相关的基础概念储备,后续我们会基于这些知识,逐步提出并优化 HTTPS 的加密方案,最终推导出完整的安全通信逻辑。现在我们可以先休息一下,接下来继续讲解 HTTPS 的五种加密方案推导过程。
HTTPS 的工作过程探究
接下来我们正式讲解 HTTPS 的具体工作过程,我会依次提出几种通信加密方案,逐一分析优缺点与漏洞,帮大家一步步推导出 HTTPS 的完整逻辑。
既然要保证数据安全,就需要进行 "加密"。网络传输中不再直接传输明文了,而是加密之后的 "密文"。加密的方式有很多,但是整体可以分成两大类:对称加密 和 非对称加密
方案 1 - 只使用对称加密
如果通信双方都各自持有同一个密钥X,且没有别人知道,这两方的通信安全当然是可以被保证的(除非密钥被破解)。

这种方案的思路很简单:客户端与服务器使用同一个对称密钥 X 进行通信。客户端用密钥 X 把明文请求加密为密文发送给服务端,服务端再用同一个密钥 X 解密得到明文;响应时同理,服务端加密、客户端解密。
这个方案看似能保证数据安全,但存在致命缺陷 :密钥无法安全同步。客户端生成的密钥 X,必须先传递给服务器,双方才能正常加解密。如果直接用 HTTP 明文传输密钥,中间人可以轻易截获;如果对密钥再加密,就需要另一个密钥来加密这个密钥,陷入 "鸡生蛋、蛋生鸡" 的死循环。因此,仅使用对称加密完全不可行 ,无法解决密钥首次安全传输的问题。

方案 2 - 只使用非对称加密
非对称加密拥有公钥和私钥配对,公钥可公开、私钥自行保管,公钥加密只能私钥解密,私钥加密只能公钥解密。

流程如下:
-
服务器提前生成一对非对称密钥 ------ 公钥 P、私钥 S。
-
客户端发起请求,服务器将公钥 P 明文发送给客户端。
-
客户端用公钥 P 加密数据,发送给服务器,只有持有私钥 S 的服务器能解密。
这个方案**[ 看似 ]** 能保证客户端→服务器 的单向传输安全,但服务器→客户端的响应完全不安全:服务器只能用私钥 S 加密响应数据,客户端用公钥 P 解密。但公钥 P 是明文传输的,中间人同样能获取,进而解密、监听数据。
除此之外,非对称加密还有一个硬伤:算法复杂、运算速度极慢,全流程使用会严重降低通信效率,用户体验极差。
方案 3 - 双方都使用非对称加密
针对方案二只能单向安全的问题,我们自然会想到:让通信双方都各自持有非对称密钥对,实现双向安全。

流程如下:
-
服务器生成公钥 S、私钥 S';客户端生成公钥 C、私钥 C'。
-
双方先明文交换公钥:客户端把公钥 C 发给服务器,服务器把公钥 S 发给客户端。
-
客户端→服务器:用服务器公钥 S 加密数据,仅服务器私钥 S' 可解密。
-
服务器→客户端:用客户端公钥 C 加密数据,仅客户端私钥 C' 可解密。
这个方案理论上实现了双向安全,但依然存在两个问题:
-
通信效率极低:全程使用非对称加密,加解密速度慢,不适合大规模数据传输。
-
存在潜在安全漏洞:公钥明文交换环节依然可被中间人利用,这个漏洞我们会在后面结合中间人攻击详细说明。

方案 4 - 非对称加密 + 对称加密

先解决效率问题:服务端具有非对称公钥S和私钥S'客户端发起https请求,获取服务端公钥S
-
客户端在本地生成对称密钥
C,通过公钥S加密,发送给服务器。[ 此时密钥C,只能通过私钥S'进行解密] -
由于中间的网络设备没有私钥,即使截获了数据,也无法还原出内部的原文,也就无法获取到对称密钥(真的吗?)
服务器通过私钥S'解密,还原出客户端发送的对称密钥C。并且使用这个对称密钥加密给客户端返回的响应数据。后续客户端和服务器的通信都只用对称加密即可。由于该密钥只有客户端和服务器两个主机知道,其他主机 / 设备不知道密钥即使截获数据也没有意义。
由于对称加密的效率比非对称加密高很多,因此只是在开始阶段协商密钥的时候使用非对称加密,后续的传输仍然使用对称加密。
虽然上面已经比较接近答案了,但是依旧有安全问题。方案 2、方案 3、方案 4 都存在一个问题:如果最开始,中间人就已经开始攻击了呢?
中间人攻击 - 针对上面的场景
Man-in-the-MiddleAttack,简称**"MITM 攻击"**
确实,在方案 2/3/4 中,客户端获取到公钥S之后 ,对客户端形成的对称秘钥X用服务端给客户端的公钥S进行加密,中间人即使窃取到了数据,此时中间人确实无法解出客户端形成的密钥X,因为只有服务器有私钥S'。

但是中间人的攻击,如果在最开始握手协商的时候就进行了,那就不一定了,假设 黑客 已经成功成为中间人:
-
服务器具有非对称加密算法的公钥
S,私钥S' -
中间人具有非对称加密算法的公钥
M,私钥M' -
客户端向服务器发起请求,服务器明文传送公钥
S给客户端 -
中间人劫持数据报文,提取公钥S并保存好,然后将被劫持报文中的公钥S替换成为自己的公钥M,并将伪造报文发给客户端
-
客户端收到报文,提取公钥M(自己当然不知道公钥被更换过了),自己形成对称秘钥X,用公钥M加密X,形成报文发送给服务器
-
中间人劫持后,直接用自己的私钥M'进行解密,得到通信秘钥X,再用曾经保存的服务端公钥S加密后,将报文推送给服务器
-
服务器拿到报文,用自己的私钥S'解密,得到通信秘钥X
-
双方开始采用X进行对称加密,进行通信。但是一切都在中间人的掌握中,劫持数据,进行窃听甚至修改,都是可以的
上面的攻击方案,同样适用于方案 2,方案 3。问题本质出在哪里了呢?客户端无法确定收到的含有公钥的数据报文,就是目标服务器发送过来的!
理解数据签名
接下来我们要解决的问题是,如何让客户端知道自己收到的公钥是合法的。为此我们需要补充三个重要内容:首先是数据签名,这是一个偏技术的知识点;其次是证书,了解什么是证书;第三是证书的签发以及 CA 机构。把这三个概念讲清楚,我们才能把它们结合起来,告诉大家如何让客户端判断公钥是否合法。
首先我们来讲第一个技术概念 ------ 数据签名 。之前我们提到过数据签名,但当时重点讲的是数据指纹和数据摘要,所谓签名,其实就是把数据指纹或数据摘要再进行一次加密,得到的结果就是签名。 接下来我把这个过程讲清楚,需要强调的是,接下来讲的内容暂时和 HTTPS 没有直接关系,是一个独立的技术知识点,但后面理解 HTTPS 必须用到它。

首先是签名的过程。假设我们有一段任意数据,先通过散列函数 也就是摘要算法进行处理,生成一串散列值,这个步骤就是我们之前讲过的数据摘要,它可以把长度不一的数据变成固定长度、且唯一性极强的散列值。在得到摘要之后,我们再执行一个动作,就是签名 。签名会使用签名者的私钥对这段散列值进行加密,这里提到私钥,就说明签名者本身要持有一组非对称密钥,即包括公钥 Q 和私钥 Q'。用签名者的私钥把散列值加密后,得到的结果就是数据签名。 然后把原始数据和这个签名拼接在一起,就形成了带有签名的完整数据,原始数据依然是明文,只是额外携带了签名数据。
那么签名有什么用呢? 主要是为了验证数据有没有被篡改。验证的过程是这样的:接收方拿到带签名的数据后,先把原始数据和签名分开,一方面对原始数据使用同样的散列函数重新计算出一个新的散列值;另一方面用签名者的公钥对签名进行解密,得到原始的散列值。如果这两个散列值完全一样,就说明数据在传输过程中没有被改过,哪怕只改动一个比特位,摘要都会发生巨大变化,两边的值就无法匹配,我们就能判断数据被篡改,签名无效。
有人会问,如果我把数据改了,再重新生成一份签名不就行了吗?其实是不行的,因为验证的人只认签名者的公钥。比如签名者是我,我把私钥妥善保管,只把公钥公布给所有人,那么所有人验证时都只会用我的公钥解密签名,其他人就算改了数据,用自己的私钥重新签名,别人也不认,因为他们没有我的私钥,无法生成合法签名。这就意味着,只有持有私钥的人,才有对数据进行合法签名的权利,其他人都做不到,这就是签名带来的唯一性和权威性。
**所以数据签名有两个核心作用:**第一,当大量用户都认可同一个公钥时,持有对应私钥的人就拥有了签名权;第二,签名和验证的机制可以有效防止数据被篡改,一旦被修改就能立刻被识别出来。在 HTTP 和 HTTPS 的实际应用场景里,执行这个签名的角色,就是我们接下来要讲的 CA 机构。
当服务端申请 CA 证书的时候,CA 机构会对该服务端进行审核,并专门为该网站形成数字签名,过程如下:
-
CA 机构拥有非对称加密的私钥
A和公钥A' -
CA 机构对服务端申请的证书明文数据进行
hash,形成数据摘要 -
然后对数据摘要用 CA 私钥
A'加密,得到数字签名S
服务端申请的证书明文和数字签名S共同组成了数字证书,这样一份数字证书就可以颁发给服务端了。
引入证书
接下来我们进入第二个概念,了解 CA 机构和证书。我们的最终目标,是让 HTTPS 在握手的时候,客户端能够判断收到的公钥是否合法、可信。为此我们需要引入证书这个概念。
**在真实的 HTTPS 使用场景中,服务器想要启用 HTTPS,必须先向 CA 机构申请一份数字证书。**数字证书里包含了申请者信息、公钥信息等内容,服务器会把证书发送给浏览器,客户端从证书里拿到公钥即可。从方案一到方案四,我们一直以为客户端向服务器发请求后,拿到的只是一个公钥,但实际上,HTTPS 里客户端第一次请求得到的并不是单纯的公钥,而是一整个证书。
证书可以理解成一段结构化的数据,里面包含证书签发机构、有效期、服务器域名、服务器公钥等明文信息,同时还带有一个签名,用来防止这些明文信息被篡改。证书的生成方式,就是把明文内容先做散列得到摘要,再用签名者的私钥加密生成签名,把明文和签名组合在一起,就是一份完整的证书。所以客户端第一次请求,服务器返回的是整个证书,公钥只是证书里的一项内容。

基本说明:https://baike.baidu.com/item/CA%E8%AE%A4%E8%AF%81/6471579?fr=aladdin
这个证书可以理解成是一个结构化的字符串,里面包含了以下信息:
- 证书发布机构
- 证书有效期
- 公钥
- 证书所有者
- 签名......
**那么证书是从哪里来的呢?**答案是由 CA 机构签发。任何公司或项目想要上线 HTTPS 服务,在开发完成、准备对外提供服务之前,都必须由技术负责人向正规的 CA 机构申请证书。申请时需要提交公司营业执照、法人信息、域名、服务器生成的公钥等资料,CA 机构会对申请主体进行严格审核,确认合法有效后,才会签发证书,证书通常有 3 到 5 年的有效期。服务器拿到证书后,把它部署到 HTTPS 服务端,以后客户端访问时,服务器就会把证书发送给客户端,证明自己的合法身份。
CA 机构是权威的认证组织,在全国各地都有被认可的认证机构或授权公司,它们的作用就是对网站和服务器做身份核验,保证线上服务不是非法的、可追溯的。浏览器和操作系统在出厂时,就已经内置了所有受信任的 CA 机构的公钥,这是客户端能信任证书的基础。
证书的具体申请流程是这样的: 服务器先自己生成一组非对称密钥,即公钥和私钥,然后把公司信息、域名、公钥等内容整理成 CSR 文件提交给 CA 机构。CA 机构自己也持有一组非对称密钥,它收到申请信息后,先对这些明文数据做散列,再用自己的私钥加密生成签名,最后把服务器提交的明文信息和这个签名组合在一起,形成数字证书发回给服务器。服务器部署证书后,客户端访问时就能拿到这份带签名的证书。
**客户端拿到证书后会自动进行验证:**先把证书里的明文和签名分开,用同样的摘要算法对明文计算出新的散列值,再用浏览器内置的 CA 公钥解密签名得到原始散列值,对比两者是否一致。如果一致,说明证书没有被篡改,是合法的,里面的公钥就是可信的;如果不一致,说明证书被改动过,客户端会直接判定不安全并断开连接。
在这套机制下,中间人攻击就彻底失效了。 因为中间人没有 CA 的私钥,就算他篡改了证书里的公钥,也无法重新生成合法的签名,客户端一验证就会发现异常。只有 CA 机构拥有合法的私钥,能够签发受浏览器信任的证书,中间人没有这个权限,也就无法伪造合法的证书和公钥。
到这里,数据签名、证书、CA 机构的逻辑已经完整串联起来,我们已经具备了理解 HTTPS 最终方案的全部基础,接下来我们就可以学习最终的方案五,也就是 HTTPS 完整的握手与密钥协商流程。
方案 5 - 非对称加密 + 对称加密 + 证书认证
首先,通信的双方是客户端和服务端,而在它们开始通信之前,还有一个非常重要的角色,那就是CA 机构。
CA 机构拥有自己用来签发证书的公钥和私钥,我们记作公钥 A 和私钥 A'。 我们想要搭建 HTTPS 服务器,就必须先向 CA 机构申请证书。申请的时候,我们要带上自己的域名、服务器自己生成的非对称公钥 S、申请者信息以及其他相关资料,提交给 CA 机构。
CA 机构收到申请后,会对这些信息进行审核,然后开始签发证书。 它会把我们提交的所有明文信息做哈希散列,得到摘要,再用自己的私钥 A'对摘要加密,形成签名。最后把明文信息和签名组合在一起,就生成了数字证书,颁发给我们的 HTTPS 服务器。
服务器在申请证书时,自己也会提前生成一对非对称密钥,也就是公钥 S 和私钥 S',私钥 S'由服务器自己妥善保管,绝不泄露,公钥 S 则交给 CA 机构,放进证书里。证书部署到服务器之后,我们的 HTTPS 服务就可以正式上线,接受客户端的访问了。
当客户端过来发起 HTTPS 请求时,服务器返回的不再是单纯的公钥,而是包含公钥的数字证书。客户端拿到证书后,不会直接使用里面的公钥,而是先验证证书是否合法,这也是解决中间人攻击最关键的一步。

客户端的验证过程很明确: 首先,浏览器和操作系统里早已内置了 CA 机构的公钥 A。客户端把证书拆成明文信息和签名两部分,对明文信息用同样的哈希算法计算出新的摘要,再用 CA 的公钥 A 解开签名,得到原始摘要。如果两个摘要一致,就说明证书没有被篡改,里面的公钥是可信的;如果不一致,说明证书被人动过手脚,客户端会直接拒绝通信。
当证书验证通过、公钥被确认为合法后,客户端就会在本地随机生成一个对称密钥 X,用证书里可信的服务器公钥 S 加密,发送给服务器。服务器用自己保存的私钥 S'解密,就能得到对称密钥 X。至此,双方都拿到了相同的对称密钥,后续所有通信都会使用这个密钥进行对称加密传输,既安全又高效。

**这里我要明确几个关键点:**所有客户端都会内置信任的 CA 机构及其子机构的公钥,这就意味着,只有 CA 机构能用对应的私钥签发合法证书。中间人就算能拿到证书,也没有任何办法篡改。
**中间人不是能截获证书吗?他能不能把证书里的公钥改掉?**答案是不能。因为一旦修改证书里的任何明文内容,重新计算的哈希值就会和签名里的摘要不匹配,客户端一验证就会发现。那能不能改完内容再重新做一个签名呢?也做不到,因为签名必须用 CA 的私钥加密,而私钥只有 CA 自己知道,中间人根本拿不到。他就算自己生成一对密钥伪造签名,客户端也不认,因为客户端只认内置的 CA 公钥。
**那中间人自己也去 CA 申请一个真证书,然后整个替换掉服务器的证书,行不行?**理论上技术可以实现,但现实中根本行不通。第一,证书里包含域名,域名是唯一的,中间人申请的证书对应别的域名,客户端一比对网址就会发现不对;第二,中间人本来就是偷偷摸摸攻击,用真实身份去申请证书,等于暴露自己,完全不符合中间人攻击的逻辑。
**所以结论很明确:**证书既不能被局部篡改,也不能被整体替换。只要客户端验证证书合法,就说明访问的是可信网站,公钥安全可靠,可以放心进行密钥交换和通信。
这就是我们的方案五,也就是真实 HTTPS 的握手方案:非对称加密 + 对称加密 + 证书认证。证书认证的本质,就是验证公钥是否合法。
常见问题
为什么摘要内容在网络传输的时候一定要加密形成签名?
常见的摘要算法有:MD5 和 SHA 系列
以MD5为例,我们不需要研究具体的计算签名的过程,只需要了解MD5的特点:
- 定长:无论多长的字符串,计算出来的
MD5值都是固定长度(16 字节版本或者 32 字节版本) - 分散:源字符串只要改变一点点,最终得到的
MD5值都会差别很大 - 不可逆:通过源字符串生成
MD5很容易,但是通过MD5还原成原串理论上是不可能的
正因为MD5有这样的特性,我们可以认为如果两个字符串的MD5值相同,则认为两个字符串相同。
理解判定证书篡改的过程:(这个过程就好比判定这个身份证是不是伪造的身份证)假设我们的证书只是一个简单的字符串hello,对这个字符串计算hash值(比如md5),结果为BC4B2A76B9719D91如果hello中有任意的字符被篡改了,比如变成了hella,那么计算的md5值就会变化很大:BDBD6F9CF51F2FD8
然后我们可以把这个字符串hello和哈希值BC4B2A76B9719D91从服务器返回给客户端,此时客户端如何验证hello是否是被篡改过?那么就只要计算hello的哈希值,看看是不是BC4B2A76B9719D91即可。
但是还有个问题,如果黑客把hello篡改了,同时也把哈希值重新计算下,客户端就分辨不出来了呀。
所以被传输的哈希值不能传输明文,需要传输密文。所以,对证书明文(这里就是 "hello")hash形成散列摘要,然后 CA 使用自己的私钥加密形成签名,将hello和加密的签名合起来形成 CA 证书,颁发给服务端,当客户端请求的时候,就发送给客户端,中间人截获了,因为没有 CA 私钥,就无法更改或者整体掉包,就能安全的证明,证书的合法性。
最后,客户端通过操作系统里已经存的了的证书发布机构的公钥进行解密,还原出原始的哈希值,再进行校验。
申请证书时,我们需要提交 CSR 文件,这是什么?
服务器先要自己生成一对非对称密钥,把公钥、域名、申请者信息等打包生成 CSR 文件,提交给 CA。私钥则由服务器自己保存,用于后续解密对称密钥。我给大家提供了在线生成工具,填写信息、选择算法,就能一键生成 CSR 文件和私钥,私钥一定要保管好,不能泄露。申请证书可以找 CA 官方,也可以通过代理服务商代办,大公司一般有专门团队负责,小项目通常由项目经理负责办理。
浏览器里的信任 CA 公钥在哪里看?
以 Chrome 为例,点击右上角菜单,进入设置,在隐私和安全里找到管理证书,就能看到系统和浏览器内置的所有受信任证书、签发机构、有效期、公钥信息等。我们信任这些证书,依靠的是信任链:我们信任顶级权威机构,那么它认证授权的子机构我们也信任,就像我们信任国家,就会信任国家认可的机构一样。
为什么签名不直接加密,而是要先 hash 形成摘要?
因为原文长度不固定,直接加密效率太低。先做摘要,变成固定长度的短字符串,再用非对称加密,速度更快、开销更小,这就是先摘要再签名的原因。
如何成为中间人 - 了解
ARP 欺骗 :在局域网中,hacker经过收到ARP Request广播包,能够偷听到其它节点的(IP, MAC)地址。例,黑客收到两个主机 A,B 的地址,告诉 B(受害者),自己是 A,使得 B 在发送给 A 的数据包都被黑客截取
ICMP 攻击:由于 ICMP 协议中有重定向的报文类型,那么我们就可以伪造一个 ICMP 信息然后发送给局域网中的客户端,并伪装自己是一个更好的路由通路。从而导致目标所有的上网流量都会发送到我们指定的接口上,达到和 ARP 欺骗同样的效果
假 wifi && 假网站等
完整流程

左侧都是客户端做的事情,右侧都是服务器做的事情。
客户端:请求https://www.xxx.com
服务器:返回数字证书
客户端:证书合法性校验 → 确认加密哈希算法
- 不合法:提示
- 合法:随机生成密钥
R→ 用证书中的公钥加密R→ 传送加密后的R
服务器:用私钥解密获取R
服务器:使用R加密网页内容 → 返回加密的网页内容
客户端:使用R解密网页内容
总结
HTTPS 工作过程中涉及到的密钥有三组。
第一组(非对称加密):用于校验证书是否被篡改。服务器持有私钥(私钥在形成 CSR 文件与申请证书时获得),客户端持有公钥(操作系统包含了可信任的 CA 认证机构有哪些,同时持有对应的公钥)。服务器在客户端请求时,返回携带签名的证书。客户端通过这个公钥进行证书验证,保证证书的合法性,进一步保证证书中携带的服务端公钥权威性。
第二组(非对称加密):用于协商生成对称加密的密钥。客户端用收到的 CA 证书中的公钥(是可被信任的)给随机生成的对称加密的密钥加密,传输给服务器,服务器通过私钥解密获取到对称加密密钥。
第三组(对称加密):客户端和服务器后续传输的数据都通过这个对称密钥加密解密。
其实一切的关键都是围绕这个对称加密的密钥。其他的机制都是辅助这个密钥工作的。第二组非对称加密的密钥是为了让客户端把这个对称密钥传给服务器。第一组非对称加密的密钥是为了让客户端拿到第二组非对称加密的公钥。