加密的概念
什么是加密
加密是将待传输的 "明文" 信息做变换,生成不可直接识别的 "密文";解密则是把密文还原为明文。这个过程中用到的辅助数据,叫做 "密钥"。
为什么要加密
我们通过网络发的 HTTP 数据是明文形式,会经过路由器、运营商设备、代理服务器等多个节点,很容易被 "中间人" 劫持篡改:
比如流程图里的场景:用户想从 "千千动听服务器" 获取天天动听的下载链接,请求经过 "运营商设备" 时,被运营商识别为 "天天动听下载请求",直接把响应篡改成了 "QQ 浏览器的下载链接"------ 这就是 "运营商劫持"。

这种风险不止来自运营商:黑客也能通过类似手段劫持明文数据,比如窃取用户登录支付平台的账号、密码,或是篡改传输内容,这就是 "中间人攻击"。
中间人攻击
简称 MITM,是网络安全中典型的攻击方式,核心是攻击者偷偷插入到通信双方之间,伪装成 "中间桥梁",拦截、窃听甚至篡改双方的传输数据,而通信的双方完全没意识到 "中间多了个第三者"。
解决方案
为了避免明文传输的安全隐患,需要对信息加密;HTTPS就是在 HTTP 基础上增加了加密机制,能有效防止传输内容被劫持、篡改,保障网络信息安全。
加密方式
对称加密
核心逻辑:用同一个密钥同时做加密、解密 ------ 比如明文和密钥做运算得到密文,密文再和同一个密钥运算,就能还原成明文。
关键特点:算法简单、加密 / 解密速度快,但密钥传输是隐患(如果密钥在传的过程中被中间人截走,加密就失效了)。常用算法:DES、AES(现在主流用 AES)。
非对称加密
核心逻辑 :用两把配对的密钥(公钥 + 私钥)------ 公钥可以公开,私钥自己保管。
- 用公钥加密的内容,只有对应的私钥能解密;
- 用私钥加密的内容,只有对应的公钥能解密。
关键特点:解决了 "对称加密的密钥传输问题"(公钥不怕泄露),但运算速度很慢(比对称加密慢几十倍)。常用算法:RSA(最常用)、ECDSA。
数据摘要
核心逻辑 :不是加密,是用 Hash 函数给任意长度的原数据,生成固定长度的 "数字指纹"(比如不管文件是 1KB 还是 1GB,MD5 都生成 128 位的串)。
核心作用:验证数据有没有被篡改 ------ 只要原数据改了 1 个字节,生成的摘要就会完全不同;且是 "单向" 的(没法从摘要反推原数据)。
关键特点 :不是加密(无解密过程),仅用于 "验真",存在极低概率的 "碰撞"(不同数据生成相同摘要)。常用算法:MD5(已不推荐)、SHA256(现在主流)。
数字签名
核心逻辑 :把「数据摘要」用私钥加密,得到的结果就是 "数字签名"。验证时:
- 接收方用公钥解密签名,得到原始摘要;
- 接收方自己给收到的数据算摘要;
- 对比两个摘要 ------ 一致则说明 "数据是你发的(只有你有私钥),且没被篡改"。通俗例子:你给文件算个指纹,再用只有你有的印章(私钥)盖在指纹上;别人拿到文件后,先看印章是不是你的(用公钥验),再算文件指纹和盖章的指纹对比,就能确认文件是你发的、没被动过。
HTTPS加密探讨
思路一:对称加密
客户端和服务器约定一个专属密钥,所有数据都用这个密钥加密成密文传输 ------ 就算数据被黑客截获,没有密钥也解不开,看起来很安全。
第一个痛点:密钥管理太麻烦
服务器要同时给很多客户端提供服务:
- 如果所有客户端用同一个密钥,黑客就也能拿到了,密钥泄露了,所有通信都不安全;
- 如果给每个客户端分配不同的密钥,服务器得记录 "哪个客户端对应哪个密钥",客户端越多,维护这个对应关系的成本就越高,根本不现实。
第二个痛点:密钥协商陷入 "鸡生蛋" 死循环
为了规避密钥管理的麻烦,理想情况是:客户端和服务器在建立连接时,临时协商一个专属密钥。
但问题来了:协商密钥的过程中,密钥本身得先传给对方吧?
- 如果直接明文传密钥,黑客一拦截就拿到了,后续加密等于没用;
- 如果用对称加密传密钥,又得先有一个 "用来加密密钥的密钥"------ 可这个 "密钥的密钥" 又该怎么安全传输?这就陷入了 "先有鸡还是先有蛋" 的死循环。
思路二:使用服务器的非对称加密
核心流程
- 服务器生成公钥 S和私钥 S',把公钥 S明文传给客户端;
- 客户端发数据时:用公钥 S 加密 → 服务器用私钥 S' 解密(只有服务器能解,客户端→服务器的信道看似安全);
- 服务器发数据时:只能用私钥 S' 加密 → 客户端用公钥 S 解密。
致命问题
-
服务器→客户端的信道完全不安全 公钥 S 是明文传输的,中间人能轻松截获。当服务器用私钥 S' 加密数据时,任何持有公钥 S 的人都能解密------ 中间人拿到数据后,用公钥 S 解密就能看到内容,等于白加密。
-
公钥本身会被中间人篡改
- 服务器发公钥 S 给客户端(明文传输) → 中间人拦截,把公钥 S 换成自己的公钥 M;
- 客户端拿到假公钥 M,用它加密数据发给服务器 → 中间人拦截数据,用自己的私钥 M' 解密,看完内容后,再用服务器的真公钥 S 加密,发给服务器;
- 服务器和客户端都以为通信正常,但数据早就被中间人偷看了 ------ 这就是针对非对称加密的中间人攻击。
思路三:双方都用非对称加密
核心流程
- 服务器有公钥 S + 私钥 S' ,客户端有公钥 C + 私钥 C';
- 双方互相明文交换公钥(客户端给服务器发 C,服务器给客户端发 S);
- 客户端→服务器:用公钥 S 加密(只有 S' 能解);
- 服务器→客户端:用公钥 C 加密(只有 C' 能解)。
致命问题
-
效率极低,完全无法支撑实际传输 非对称加密的算法复杂度远高于对称加密,运算速度慢几十到上百倍
-
公钥交换的中间人攻击漏洞依然存在 方案 3 的公钥交换还是明文传输,中间人照样能篡改:
- 拦截客户端的公钥 C,换成自己的公钥 M;
- 拦截服务器的公钥 S,换成自己的公钥 N;
- 最终变成:客户端↔中间人(用 M/N 加密),中间人↔服务器(用 C/S 加密)------ 双方的通信内容还是会被中间人窃取、篡改。
思路四:非对称加密+对称加密
- 服务器持有非对称密钥对:公钥 S(公开)、私钥 S'(自己保管)。
- 客户端先拿服务器的公钥 S(明文传输):客户端发起 HTTPS 请求,服务器把公钥 S 明文传给客户端。
- 客户端生成对称密钥 C:。
- 用公钥 S 加密对称密钥 C:客户端把 "加密后的 C" 发给服务器
- 服务器解密拿到 C:只有服务器的私钥 S' 能解开 "加密后的 C",还原出对称密钥。
- 后续用对称密钥通信:客户端和服务器的所有数据,都用对称加密 / 解密------ 既安全又高效。
致命漏洞:公钥被中间人篡改了!
思路四的所有安全,都建立在 "客户端拿到的公钥 S 是服务器的真公钥 " 这个前提上。但如果中间人在 "第一步" 就动手,这个前提会直接崩塌:
- 服务器给客户端发真公钥 S → 中间人拦截,把 S 换成自己的公钥 M;
- 客户端以为拿到的 M 是服务器的真公钥,用 M 加密对称密钥 C(888888),发给服务器;
- 中间人拦截 "加密后的 C",用自己的私钥 M' 解密,直接拿到对称密钥 888888;
- 中间人再用服务器的真公钥 S 加密 888888,发给服务器;
- 后续客户端和服务器用 888888 对称加密通信时,中间人已经拿到了密钥 ------ 既能解密看内容,又能篡改后重新加密转发,而客户端和服务器完全不知情。
CA认证
CA(Certificate Authority,证书颁发机构)是全球公认的权威第三方机构------ 它的核心职责是:
- 验证服务器的真实身份(比如证明 "这个公钥确实属于
www.baidu.com"); - 给服务器的公钥 "盖权威公章"(生成数字证书),让浏览器相信 "这个公钥是真的"。
CA中心为每个使用公开密钥的用户发放一个数字证书,数字证书的作用是证明证书中列出的用户合法拥有证书中列出的公开密钥。CA机构的数字签名使得攻击者不能伪造和篡改证书。
浏览器 / 操作系统会预装全球主流 CA 的公钥(比如 VeriSign、Let's Encrypt 等),只要是这些 CA 签发的证书,浏览器就会默认信任。
证书的完整申请流程(服务器如何拿到证书)
服务器要使用 HTTPS,必须先向 CA 申请证书,流程是:
-
服务器生成自己的密钥对 :服务器自己生成一对非对称密钥(记为 "服务器公钥 S"+"服务器私钥 S'")------ 这对密钥是服务器自己用的,私钥 S' 必须严格保管,不能泄露。
-
生成 CSR 文件(证书请求):服务器创建一个 "CSR 文件"(Certificate Signing Request,证书签名请求),里面包含:
- 服务器的身份信息(比如域名
www.xxx.com、公司名称); - 服务器自己的公钥 S(注意:私钥 S' 不会出现在 CSR 里)。
- 这个文件可以使用第三方工具生成CSR在线生成工具。
- 形成CSR之后,后续就是向CA进行申请认证,不过⼀般认证过程很繁琐,网络各种提供证书申请的服务商,一般真的需要,直接找平台解决。
- 服务器的身份信息(比如域名
-
提交 CSR 给 CA,完成身份验证 :服务器把 CSR 文件发给 CA,CA 会验证 "这个 CSR 对应的服务器身份是否真实"------ 比如验证 "你确实是
www.xxx.com的所有者"(可能需要你在域名解析里加一条记录,或上传验证文件到服务器)。 -
CA 签发数字证书 :验证通过后,CA 会生成一份数字证书(包含服务器信息 + CA 的签名),并把证书发给服务器。
数字证书的核心内容
证书相当于一个网络身份证,本质是一个结构化的文件,核心包含 5 类信息。
| 证书字段 | 作用 |
|---|---|
| 证书发布机构(CA) | 说明 "这份证书是哪个权威 CA 签发的"(比如 Let's Encrypt) |
| 证书有效期 | 防止证书被长期滥用(一般 1-2 年,过期后需要重新申请) |
| 证书所有者 | 说明 "这份证书对应的服务器是谁"(比如域名www.xxx.com、公司名称) |
| 服务器公钥 | 服务器自己生成的公钥 S(这是证书的核心,浏览器要靠它加密数据) |
| 数字签名 | CA 给这份证书盖的 "权威公章"(防止证书被篡改) |
CA 如何生成 "数字签名"
数字签名是证书的 "防伪核心",生成过程结合了数据摘要 + CA 的非对称加密,步骤是:
- CA 有自己的密钥对:CA 自己持有 "CA 公钥 A"(预装在浏览器里)和 "CA 私钥 A'"(CA 严格保密,绝不泄露)。
- CA 对证书明文做哈希,生成摘要:CA 把证书里的 "发布机构、有效期、服务器公钥、所有者" 等明文信息,用 Hash 算法(比如 SHA256)生成一个固定长度的数据摘要------ 只要证书明文改了 1 个字节,摘要就会完全不同。
- CA 用自己的私钥 A' 加密摘要,得到数字签名:CA 把生成的摘要,用自己的私钥 A' 加密,得到的密文就是 "数字签名"。
最后,CA 把 "证书明文 + 数字签名" 打包,就是发给服务器的最终数字证书。
浏览器如何验证证书(防止公钥被篡改)
浏览器拿到服务器的证书后,会自动完成验证,确保 "这个证书是真的、公钥没被篡改",步骤是:
- 从系统里拿到对应 CA 的公钥 A:浏览器 / 操作系统预装了 CA 的公钥 A,比如证书是 Let's Encrypt 签发的,就用 Let's Encrypt 的公钥 A。
- 用 CA 公钥 A 解密 "数字签名",得到原始摘要:因为签名是 CA 用私钥 A' 加密的,所以只有 CA 的公钥 A 能解密,得到 CA 当初生成的摘要(记为 "摘要 1")。
- 浏览器自己对证书明文做哈希,生成新摘要:浏览器把证书里的明文信息(发布机构、有效期、服务器公钥等),用和 CA 一样的 Hash 算法,生成一个新的摘要(记为 "摘要 2")。
- 对比摘要 1 和摘要 2:
- 如果一致:说明证书明文没被篡改,服务器公钥 S 是真的;
- 如果不一致:说明证书被中间人篡改过(比如把服务器公钥 S 换成了中间人自己的公钥),浏览器会弹出 "安全风险" 提示,阻止用户访问。
证书如何解决之前的 "公钥篡改漏洞"
回到方案 4 的漏洞:中间人原本可以替换服务器的公钥,但有了证书后:
- 中间人如果把证书里的 "服务器公钥 S" 换成自己的公钥 M,证书明文就变了;
- 浏览器验证时,自己生成的 "摘要 2" 会和 "解密签名得到的摘要 1" 不一致;
- 浏览器直接提示 "证书不可信",用户不会继续访问 ------ 中间人篡改公钥的操作彻底失效。
HTTPS 的安全方案(非对称 + 对称 + 证书)
这是 HTTPS 实际用的方案,核心是用证书解决 "公钥信任问题",流程是:
- 服务器提前向 CA 申请 "包含自己公钥 + CA 签名" 的证书;
- 客户端与服务器建立连接时,服务器先把证书发给客户端;
- 客户端验证证书(确认 "这个公钥确实是目标服务器的");
- 验证通过后,客户端用证书里的公钥加密 "对称密钥",发给服务器;
- 后续通信都用这个对称密钥加密(高效 + 安全)。
中间人攻击的两种操作,为什么都失败?
1. 篡改证书内容(比如改公钥)
中间人可以修改证书的明文(比如把服务器公钥换成自己的),但没法生成匹配的有效签名:
- 签名是 "CA 用私钥加密证书摘要" 生成的,中间人没有 CA 私钥;
- 客户端验证时,会发现 "证书明文的摘要" 和 "签名解密后的摘要" 不一致,直接判定证书被篡改,终止通信。
2. 掉包成自己的证书
中间人可以自己向 CA 申请一份证书,但客户端会通过 "证书里的域名" 识破:
- 证书里包含 "服务器的域名"(比如目标是
cdn.qq.com),中间人自己的证书,域名是他自己的(比如xxx.com); - 客户端收到证书后,会检查 "证书里的域名是否和自己访问的域名一致",不一致就判定是假证书,阻止访问。
为什么签名要先 Hash 生成摘要,而不直接加密整个证书?
- 证书的明文内容可能很长(包含域名、有效期、公钥等),直接用非对称加密整个证书,运算速度会非常慢(非对称加密的效率和数据长度正相关);
- 把证书 Hash 成固定长度的摘要(比如 SHA256 是 256 位),再加密摘要,既能保证 "只要证书内容变,摘要就变",又能大幅缩小加密的数据量,让签名 / 验证的速度快很多。
