🎬 胖咕噜的稞达鸭 :个人主页
🔥 个人专栏 : 《数据结构》《C++初阶高阶》
《Linux系统学习》
《算法日记》
⛺️技术的杠杆,撬动整个世界!
中间人攻击:
中间人攻击的本质,是攻击者插入客户端和服务器之间,分别与双方建立独立连接。 客户端如果没有正确验证服务器证书,就可能把中间人的公钥误认为服务器公钥,导致后续加密数据实际上先被中间人解密。这样攻击者不仅可以窃听通信内容,还可能篡改数据后再转发给真正服务器。
所以 TLS/HTTPS 里证书校验的核心作用,就是防止中间人伪造身份、替换公钥。
大白话来理解:表面上是你在跟官网聊天,实际上是你先跟骗子聊,骗子再转头跟官网聊,你说的每一句话他都能先看一遍,想改还能改。
核心问题还是:客户端无法甄别自己收到的公钥是不是合法的。(到底是中间人篡改过的还是服务器端给的原本的公钥)
CA证书与签名
刚刚我们谈到了就是因为客户端无法分别自己一开始收到的公钥到底是不是合法的,所以才会让中间人mid钻了空子,将服务器端首次交给客户端的公钥进行恶意篡改,然后导致客户端和服务器端都不清楚自己收到的数据+公钥是不是合法的,这才导致数据泄漏,在局域网中裸奔。

cpp
私钥 Q(只有你持有)→ 签名 → 数据 + 签名
↓
公钥 P(公开分发)← 验证 ← 客户端收到
- 只有私钥持有者能签名 ✓
- 中间人篡改后无法伪造签名 ✓
- 签名验证失败 = 被篡改 ✓
这个签名者其实就是CA机构,张三那些人是客户端。


总结:
- 服务器会先生成一对密钥,也就是公钥和私钥,然后把域名、申请者信息和公钥整理成证书申请文件发给
CA。CA在审核通过之后,会把这些公开信息和 CA 自己的签名一起做成证书发回给服务器。- 之后服务器在和客户端建立连接时,把这个证书发给客户端。
- 客户端会用
CA的公钥去验证证书上的签名,同时检查域名、有效期、吊销状态等信息。如果这些都没问题,就说明这个服务器身份可信- 后续双方再基于这个可信身份去协商通信加密所需要的会话密钥。
方案五:非对称加密 + 对称加密 + 证书认证

问题:如果说认证证书的合法性,就是认证公钥是否与CA机构的公钥是一致的,但是浏览器等客户端内部内置有CA机构的公钥啊,他可以直接把内置的这把公钥跟证书中提供的证书做对比啊,就可以验证合法性了,还算什么散列值啊?
- 首先这个问题的理解不对,浏览器等客户端内部内置的公钥 跟 证书中提供的公钥 不是同一把,证书中提供的公钥是服务器自己的公钥,客户端内置的公钥是
CA机构权威认证的。两者不可同一而语;- 其次客户端在验证的目的是证书内容有没有被
CA机构盖章认证 ,浏览器会先对证书明文信息计算哈希,再用内置的CA公钥验证签名得到原始摘要,如果两者一致,说明证书内容没有被篡改,并且确实是受信任的 CA 签发的。
问题:几把钥匙是怎么用的?
CA的公钥 :内置在客户端中用来解密服务器端发送的数据形成的散列值,用来验证服务器证书上的 CA 签名。- CA的私钥 :CA自己用,绝对不交给任何人,用来对申请上线认证证书的内容做签名,私钥加密散列值 + 数据形成带有 CA 签名的数字证书。
- 服务器的公钥S' :两个用途,第一个是用来申请CA证书认证时写到申请资料中的,为了求得官方认可;第二个作为服务器证书的一部分在服务器做应答的时候发送给客户端,让客户端信任这把服务器公钥确实属于这个网站;
- 服务器的私钥S':只在服务器自己手里,用来证明"我确实是这张证书对应的人",并参与
TLS握手。后续真正传输数据,主要还是靠会话密钥。
由此,我们凭借这几把钥匙 + CA机构 + 证书签名 就会防范中间人,中间人根本就无法插入到其中捣乱,既不能签署证书,也不能解密散列值。
完整流程:

HTTPS 握手流程:
- 浏览器先找服务器要 "身份证":我输入网址,浏览器先问服务器:"你是谁?给我看看你的身份证(数字证书)。"
- 浏览器查身份证真假:浏览器拿到证书后,会去查这个证是不是权威机构发的、有没有过期、是不是被篡改过。如果有问题,直接弹 "不安全";没问题就继续。
- 浏览器生成一个 "暗号",用服务器的公钥锁起来发过去:我这边随机生成一个密钥 R,用服务器证书里的公钥把 R 加密,再发给服务器。这样就算被人截了,没有服务器的私钥也解不开。
- 服务器用自己的私钥解开,拿到暗号:服务器收到加密的 R,用自己的私钥解开,拿到了这个暗号 R。
- 之后所有聊天都用这个暗号加密:服务器用 R 加密网页内容发给我,我用 R 解密看内容。这样既安全又快。
一句话总结:先靠非对称加密安全地把 "暗号" 传给对方,之后用这个 "暗号" 加密聊天,既安全又高效。
问题:有了这个方案五(非对称加密 + 对称加密 + 证书),怎么说明HTTPS 比 HTTP通信更加安全的?

HTTP是明文传输,客户端和服务器端通信的信息都是肉眼可见的,随意使用一个抓包工具都可以获取到通信的内容。安全上存在风险。
HTTPS在HTTP与TCP层之间加入了TLS协议,来解决HTTP通信数据在局域网中裸奔的问题:
信息加密:HTTP交互信息是被加密的,第三方就无法获取;
校验机制:校验信息传输过程中是不是被中间人攻击过,攻击过就会有的"网站不安全"的提示;
身份证书:CA认证过的合法网站。
刚刚我们所说的方案五其实就是TLS协议的内核。
现在来说明一下TLS握手的过程:

第一次握手:
客户端首先会发一个Client Hello消息,字面意思我们也能理解到,这是跟服务器打招呼。
消息里面有客户端使用的TLS 版本号、支持的密码套件列表,以及生成的随机数(Client Random)这个随机数会被服务端保留,它是生成对称加密密钥的材料之一。
第二次握手:
当服务端收到客户端的Client Hello消息后,会确认 TLS 版本号是否支持,和从密码套件列表中选择一个密码套件,以及生成随机数(Server Random)。
接着,返回Server Hello消息,消息里面有服务器确认的 TLS 版本号,也给出了随机数(Server Random),然后从客户端的密码套件列表选择了一个合适的密码套件。
就前面这两个客户端和服务端相互「打招呼」的过程,客户端和服务端就已确认了 TLS 版本和使用的密码套件,而且你可能发现客户端和服务端都会各自生成一个随机数,并且还会把随机数传递给对方。
问题:那这个随机数有啥用呢?
其实这两个随机数是后续作为生成「会话密钥」的条件,所谓的会话密钥就是数据传输时,所使用的对称加密密钥。然后,服务端为了证明自己的身份,会发送「Server Certificate」给客户端,这个消息里含有数字证书。
第三次握手:
客户端验证完证书后,认为可信则继续往下走。接着,客户端就会生成一个新的随机数 (pre-master),用服务器的 RSA 公钥加密该随机数,通过「Client Key Exchange」消息传给服务端。
服务端收到后,用 RSA 私钥解密,得到客户端发来的随机数 (pre-master)。
至此,客户端和服务端双方都共享了三个随机数,分别是 Client Random、Server Random、pre-master。于是,双方根据已经得到的三个随机数,生成会话密钥(Master Secret),它是对称密钥,用于对后续的 HTTP 请求/响应的数据加解密。
生成完「会话密钥」后,然后客户端发一个「Change Cipher Spec」,告诉服务端开始使用加密方式发送消息。
然后,客户端再发一个「Encrypted Handshake Message(Finishd)」消息,把之前所有发送的数据做个摘要,再用会话密钥(master secret)加密一下,让服务器做个验证,验证加密通信「是否可用」和「之前握手信息是否有被中途篡改过」。
可以发现,「Change Cipher Spec」之前传输的 TLS 握手数据都是明文,之后都是对称密钥加密的密文。
第四次握手:
服务器也是同样的操作,发「Change Cipher Spec」和「Encrypted Handshake Message」消息,如果双方都验证加密和解密没问题,那么握手正式完成。最后,就用「会话密钥」加解密 HTTP 请求和响应了。