目录
HTTPS 中间人攻击与数字证书原理解析
一、中间人攻击(MITM)问题
在介绍数字证书之前,先来看一个经典的安全问题——中间人攻击
假设客户端需要与服务器建立安全通信,于是客户端向服务器请求其公钥。
正常流程如下:
-
客户端向服务器请求公钥;
-
服务器将自己的公钥返回给客户端;
-
客户端使用服务器公钥加密数据;
-
服务器使用自己的私钥解密数据。
看起来非常安全,但实际上仍然存在风险。
如果通信链路中存在一个黑客(中间人),那么当服务器返回公钥时,黑客可以拦截该公钥,并将其替换成自己的公钥后再发送给客户端。
此时通信流程变成:
-
客户端请求服务器公钥;
-
黑客拦截服务器返回的公钥;
-
黑客将自己的公钥发送给客户端;
-
客户端误以为这是服务器公钥,并使用其加密数据;
-
黑客使用自己的私钥解密数据,获取明文内容;
-
黑客再使用真正服务器的公钥加密数据并转发给服务器。
中间人攻击原理图

整个过程中:
-
客户端认为自己正在与服务器通信;
-
服务器认为自己正在与客户端通信;
-
实际上所有数据都经过了黑客。
这就是典型的中间人攻击。
由此可见,仅依靠非对称加密并不能解决“公钥是否可信”的问题。
二、数字证书的作用
为了解决公钥真实性的问题,人们引入了数字证书(Certificate)。
数字证书由权威的第三方机构——CA(Certificate Authority,证书颁发机构)签发。
服务器需要先向 CA 申请证书,CA 验证服务器身份后,向服务器颁发证书。
证书中通常包含以下内容:
-
证书颁发机构(CA)
-
证书有效期
-
服务器公钥
-
服务器所属域名
-
数字签名
CA证书签发流程图

证书本身并不负责加密通信,它的核心作用是:
证明服务器公钥的真实性。
客户端通过验证证书,可以确认拿到的公钥确实属于目标服务器,而不是黑客伪造的公钥。
三、数字证书如何防止公钥被篡改
有人可能会问:
既然证书中也保存着服务器公钥,那么黑客能不能直接修改证书中的公钥呢?
答案是:
可以修改内容,但无法通过验证。
原因就在于数字签名机制。
客户端拿到证书后会进行以下验证:
-
使用 CA 公钥解密数字签名,得到校验值 A;
-
使用相同哈希算法对证书内容重新计算哈希值,得到校验值 B;
-
比较 A 与 B 是否一致。

如果一致,说明证书未被篡改;
如果不一致,说明证书内容在传输过程中被修改,客户端会直接判定证书无效并终止连接。
四、为什么修改证书内容后数字签名会失效
1. HTTPS 数字签名流程
数字签名的生成过程如下:
CA 签发证书
-
对证书原文进行哈希运算(通常使用 SHA-256);
-
得到哈希值(校验和);
-
使用 CA 私钥对该哈希值进行加密;
-
生成数字签名并写入证书。
客户端验证证书
-
使用 CA 公钥解密数字签名;
-
得到原始哈希值;
-
对证书内容重新计算哈希值;
-
对比两个哈希值。
如果两者一致,则证书合法。

2. 黑客为什么无法伪造证书
(1)哈希算法不可逆
SHA-256 属于单向哈希函数:
-
可以通过原文计算哈希值;
-
无法通过哈希值反推出原文。
同时,现代安全哈希算法具有极强的抗碰撞能力。
也就是说:
想要构造两份不同内容却拥有完全相同哈希值的数据,在现实中几乎不可行。
(2)无法伪造 CA 的数字签名
数字签名的生成必须使用 CA 私钥。
而客户端验证签名使用的是 CA 公钥。
因此:
-
CA 公钥只能用于验证签名;
-
无法用于生成新的签名。
黑客即使修改了证书内容,也无法重新生成合法签名,因为其并不持有 CA 私钥。
(3)篡改内容必然导致校验失败
证书内容一旦发生变化:
-
客户端重新计算出的哈希值会改变;
-
数字签名解密出的哈希值不会改变;
最终两个哈希值不一致。
因此客户端会立即发现证书被篡改,并拒绝建立连接。
3. 数字签名是否固定
数字签名并不是一个固定值,而是随着内容变化而变化。
其特点如下:
-
同一份内容生成的签名是固定的;
-
内容只要修改一个字节,哈希值就会完全不同;
-
哈希值变化后,数字签名也会完全变化。
因此,数字签名与证书内容是一一对应的关系。
五、总结
HTTPS 通过引入 CA 数字证书,解决了非对称加密中“公钥真实性无法验证”的问题。
其核心思想是:
利用可信第三方(CA)对服务器公钥进行担保。
这样客户端就能够确认:
-
当前拿到的公钥确实属于目标服务器;
-
公钥在传输过程中没有被篡改;
-
黑客无法伪造合法证书。
因此,数字证书从根本上阻断了黑客通过伪造服务器公钥实施中间人攻击的途径。
TCP 连接断开:四次挥手
TCP 连接建立采用三次握手,而连接释放采用四次挥手。

为什么是四次挥手?
当一方发送 FIN 报文表示“我没有数据要发送了”时:
-
对方内核收到 FIN;
-
内核立即返回 ACK;
-
ACK 的发送由 TCP 协议栈自动完成,与应用程序代码无关;
-
应用程序处理完剩余数据后,调用
close(); -
TCP 再发送自己的 FIN。
因此:
-
ACK 和 FIN 往往不是同时发送;
-
TCP 需要拆分成两个独立步骤;
-
最终形成四次挥手。
三次握手与四次挥手的发起方
三次握手
连接建立时:
-
第一次 SYN 一定由客户端发起;
-
因此三次握手总是以客户端发送 SYN 开始。
四次挥手
连接断开时:
-
客户端可以主动关闭连接;
-
服务器也可以主动关闭连接;
谁先调用 close(),谁就是主动关闭方。
TIME_WAIT 与 CLOSE_WAIT
在连接释放过程中:
主动关闭方
发送 FIN 后,会进入:
TIME_WAIT 状态
作用:
-
保证最后一个 ACK 能够成功到达对方;
-
防止旧连接中的延迟报文影响新的连接。
被动关闭方
收到 FIN 后,会进入:
CLOSE_WAIT 状态
此时说明:
-
TCP 已经确认收到对方关闭请求;
-
应用程序仍有数据需要处理;
-
等待应用程序调用
close()后再发送 FIN。
因此:
-
主动关闭方进入 TIME_WAIT;
-
被动关闭方进入 CLOSE_WAIT。

387

被折叠的 条评论
为什么被折叠?



