万字长文深度解析HTTPS协议

发布于:2025-08-19 ⋅ 阅读:(16) ⋅ 点赞:(0)

作者:唐叔在学习
专栏:IT技术深度理解

一、创作背景

其实关于HTTPS,唐叔之前就写过一篇《SSL/TLS协议深度解析》,那篇文章可是把我自己的理解加上AI小伙伴的润色才搞定的。不过后来有读者留言问:“SSL/TLS协议是怎么保证网络通信安全的?”

在这里插入图片描述

哎呀,被这么一问,我才发现确实没把整个握手过程讲透。这不,痛定思痛之后,我这次可是下了狠功夫——整整一周抱着《图解HTTP》死磕,把每个细节都吃透了。这回要是还讲不明白,我唐字倒着写!

二、基础知识

各位同学注意啦!在咱们正式开始之前,唐叔得先给完全零基础的小伙伴们补补课~毕竟现在上网冲浪这事儿,对咱们来说就跟喝水一样自然,但背后的原理可有趣着呢!

想象一下:你在浏览器里随手输入"测试"两个字,啪的一下回车,唰唰唰就跳出一堆搜索结果。这在90年代的人看来,简直就是魔法好吗!比翻百科全书快多了有木有!那这个"魔法"到底是咋实现的呢?让唐叔用最接地气的方式给你捋一捋:

  1. 首先呢,你的电脑连上网后,就相当于互联网海洋里的一条小鱼(客户端啦)

  2. 你输入"测试"点击搜索,其实就是朝谷歌/百度这些"大海怪"(服务端)喊话:“喂!给我’测试’的资料!”

  3. 你这句话会被拆成数据包,像漂流瓶一样经过无数路由器中转,最后飘到服务器手里

  4. 服务器老哥收到后,赶紧翻自己的数据库,把关于"测试"的资料打包成数据包再给你寄回来

(小声bb:其实搜索引擎更复杂,它还会先去其他网站"偷"数据存起来…)

在这里插入图片描述

是不是还有点抽象?别急!唐叔再给你画个更具体的路线图~整个过程就像快递送货,要经过四步:

✨ 应用层:你平时用的所有网站APP都在这一层,当你要传输数据,就类似申请"寄快递"
✨ 传输层:负责确保数据完整送达,著名的"TCP三次握手"就是这里的快递小哥,会把你的快递用"TCP"包装起来
✨ 网络层:相当于快递分拣中心,靠IP地址(比如192.168.1.1)来认路,相当于根据你填写的IP地址确定发货路线
✨ 数据链路层:就是实实在在的网线、WiFi这些"运输工具",整个互联网相当于由各个交通枢纽和设施构成

(PS:按《图解HTTP》的说法是四层啦,大学教材会更细,但唐叔觉得这样好记~)

在这里插入图片描述

可能有同学要喊了:“唐叔你越说我越晕啊!” 但是没办法呀,HTTPS中最重要的SSL/TLS这个保镖就是在这些快递站之间巡逻的,咱们得先知道快递怎么送,才能明白保镖在哪站岗对不对?(๑•̀ㅂ•́)و✧

三、HTTP局限性

好啦,看完上面的介绍,你是不是觉得HTTP也就那么回事儿嘛~不就是传个数据嘛,小菜一碟!( ̄▽ ̄)~*

但是!今天咱们要聊的是它的升级版——HTTPS!既然说HTTPS更安全,其实也等于在说HTTP不安全!接下来就让唐叔给你扒一扒HTTP的三大"致命伤":

🔓 第一宗罪:裸奔式传输

  • 你发的所有信息都是明码标价…啊不是,是明文明码!就像在广场上大声喊出你的银行卡密码一样刺激!

在这里插入图片描述

(下图是用抓包工具抓取的某小说网站的HTTP请求数据。而实际上用户的HTTP请求,在请求发往服务端的整个过程中都可能被抓取。 就比如:你用WIFI上网,在路由器上部署代理服务器,就可以记录所有经过的流量数据了)

在这里插入图片描述

🕵️ 第二宗罪:认贼作父

  • 根本不管对方是淘宝官网还是钓鱼网站,谁来都接待!就像把家门密码告诉每个自称是快递员的人…

在这里插入图片描述

(实际上通信双方都可能被伪装。最常见的伪装服务端莫过于一些模仿正规官网网站的钓鱼网站链接,如果不加识别,真以为是官网)

在这里插入图片描述

2025年7月被投诉钓鱼网站TOP10_腾讯新闻

✂️ 第三宗罪:任人宰割

  • 数据在路上被篡改了都不知道!就像你寄出的情书被人偷偷改成了辞职信…

在这里插入图片描述

常见的有ARP欺骗、DNS欺骗等。

在这里插入图片描述

图为ARP欺骗交互图,192.168.43.36 是靶机,192.168.43.195 是攻击者,192.168.43.1 是路由器。

正常交互是:靶机将请求发送路由器,路由器再外发公网,而后路由器接收公网数据,再分发靶机。

而通过ARP欺骗:让靶机以为攻击者是路由器,让实际路由器以为攻击者是靶机,最终靶机和路由器的交互数据都被攻击者截获。

术语说明:

  • 靶机:被攻击的目标设备或系统;

  • 攻击者:模拟黑客行为的设备或角色;

  • 路由器:网络中负责流量转发的设备,可能作为攻击路径的一部分

在这里插入图片描述

(图为靶机被攻击后,访问 baidu.com 网页被篡改示例)

四、HTTP安全加固

讲解完HTTP局限性,这下知道为啥说HTTP不安全了吧。

哪HTTPS是如何做到安全可信的呢?这一章节,就让唐叔给你细细道来。

首先,针对HTTP的第一宗罪 - 裸奔式传输,既然明文存在风险,那就加密呗。加密了就算被攻击者窃取到密文数据,攻击者也用不了。但是呢,加密要保障实际通信双方不受影响,比如客户端加密传输请求,服务端必须能解密获取明文内容,如果服务端无法解密获取明文数据,那么也就无法针对用户请求进行相应的业务处理和数据响应。

在这里插入图片描述

也就是说,要设计一种数据加密传输方式,攻击者无法获取解密后的数据,但是通信双方又可以最终知晓明文内容。这种既要又要的方式是否能实现呢。

🔒加固1:加密算法

在讲解HTTPS的密文传输具体实现前,唐叔有必要科普下当前市面上主流的几类加密算法。

PS:其实唐叔前阵子也写了相关的加密算法文章的 – 常见加密算法详解 - 程序员必知的网络安全基石_数据加密方法csdn-CSDN博客

❎不可逆加密算法

使用不可逆加密算法进行加密,是不可逆转的 – 即只能加密无法解密,但相同内容每次加密后密文都是相同的。

最常见的有哈希算法等。各大编程语言其实都有内置的加密算法实现的,下面以Python MD5加密算法实现为例。

import hashlib

def md5_hash(text):
    md5 = hashlib.md5()
    md5.update(text.encode('utf-8'))
    return md5.hexdigest()

if __name__ == "__main__":
    text = "唐叔讲算法"
    print(f"MD5哈希值: {md5_hash(text)}")
    # 输出示例: a7d8cd9e89d4f5c37f5a7d82b5a3c3f1

这类算法很适合用于用户密码的密文存储,有效保障密码密文在存储后即使外泄也无法解密获取原密码,而业务使用时,只需校验用户输入的密码加密后与存储的密文是否一致即可。

但是很显然,因为加密不可逆转,这种密码无法作为HTTP数据加密传输使用。客户端使用该类算法加密后,发送数据给服务端,

🗝️可逆加密算法

和不可逆加密算法相对应的自然是可逆加密算法,即相同内容加密后,也可以加密出原内容。

该类算法具体又分为对称加密算法和非对称加密算法。也就是主流加密算法实际上有这几类:

示例
示例
示例
加密算法
不可逆加密算法
可逆加密算法
对称加密算法
非对称加密算法
MD5, SHA-1, SHA-256等哈希算法
AES, DES, 3DES, RC4
RSA, ECC, ElGamal, DSA

先说说可逆加密算法,其加密过程本质上是一个确定的数学变换,且该变换必须存在对应的逆运算。就像 y = f ( x ) + z y=f(x) + z y=f(x)+z,通过 x x x 可以推导出 y y y, 通过 y y y 也可以逆运算推导出 x x x。可逆加密算法也是如此,只是算法涉及的 y y y x x x 的转换较为复杂。

和不可逆加密算法一样,可逆加密算法的具体实现是公开的。以 AES 算法为例,下面是其Python实现。

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
import base64

def aes_encrypt(plaintext, key=None):
    if key is None:
        key = get_random_bytes(16)  # AES-128

    # 生成随机初始化向量
    iv = get_random_bytes(AES.block_size)

    cipher = AES.new(key, AES.MODE_CBC, iv)
    ciphertext = cipher.encrypt(pad(plaintext.encode('utf-8'), AES.block_size))

    return iv, ciphertext, key

def aes_decrypt(iv, ciphertext, key):
    cipher = AES.new(key, AES.MODE_CBC, iv)
    plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
    return plaintext.decode('utf-8')

if __name__ == "__main__":
    message = "敏感数据"

    iv, ciphertext, key = aes_encrypt(message)

    print(f"密钥: {base64.b64encode(key).decode()}")
    print(f"IV: {base64.b64encode(iv).decode()}")
    print(f"加密结果: {base64.b64encode(ciphertext).decode()}")

    decrypted = aes_decrypt(iv, ciphertext, key)
    print(f"解密结果: {decrypted}")

算法都公开了,哪怎么做到用户自身可以解密,其他人不可以解密呢?

核心就在于 y = f ( x ) + z y=f(x)+z y=f(x)+z z z z。虽然可逆加密算法公开了 f ( x ) f(x) f(x),但是 z z z 是使用算法的用户自行设定的,没有 z z z,知道算法也是无法解密的。在可逆加密算法中,我们把 z z z,称为 密钥

可逆加密算法中,对称加密算法和非对称加密算法的区别就在于密钥的使用。

  • 对称加密算法,加密和解密使用的是相同的密钥。即
    • 加密:密文 = 加密算法(明文, 密钥)
    • 解密:明文 = 解密算法(密文, 密钥)
  • 非对称加密算法,使用一对数学上关联的公钥和私钥,通过公私钥的指数运算互为逆操作实现逆反运算。即
    • 加密:密文 = 明文^公钥 mod N
    • 解密:明文 = 密文^私钥 mod N

💡温馨提示:非对称加密算法,只能是"公钥加密&私钥解密",或"私钥签名&公钥验签"(该场景严格说不是加密),没有"私钥加密&公钥解密"一说。

哪最终HTTPS使用的是对称加密算法还是非对称加密算法呢?

在这里插入图片描述

答案是:两者兼具(PS:小孩子还选择,大人我全要)。

🔩HTTP加密算法使用

实现HTTP加密传输,但是最终又能解密,很显然只要是可逆加密算法都可行。

不过难点就在于怎么实现将密钥传递给通信双方,而不被第三方获取。

直接用对称加密算法呢,是做不到的,在通信双方数据传输过程都可能被攻击者截获,导致密钥泄露。

在这里插入图片描述

用非对称加密算法方式呢?方法可行。

在这里插入图片描述

不过呢,基于非对称加密算法的性能体验远差于对称加密算法(有验证分析相差千倍)。因而,实际HTTPS是对称加密算法和非对称加密算法混合使用。

  • 服务器端生成一组公钥私钥。然后分发公钥给客户端。

  • 客户端使用公钥加密对称密钥,并将密文发送给服务器端。

  • 服务器端使用私钥解密后,获取到对称密钥。

  • 之后的客户端和服务器端数据交互,就直接使用对称密钥加密数据进行传输交互。

在这里插入图片描述

🏛️ 加固2:第三方认证

当HTTP完成上述加密后,就安全了嘛?实际上还不够。

通过上述手段,只能解决明文传输问题,但是针对HTTP的第二宗罪,却依然无可奈何。攻击者虽然无法获取通信双方正常的通信内容,但是可以在双方建立通信前,伪装成通信的任一方,同时伪造密钥来达到欺骗通信方,进而导致攻击者可以用自身私钥解密客户端的数据,解密数据后又用服务器端公钥加密后转发服务器,从而做到神不知鬼不觉的获取到通信双方的数据。

在这里插入图片描述

该怎么处理这种信任问题呢?在解答前,我们先来看看互联网的交易方式呢。

在这里插入图片描述

网络交易中,用户和商家并不是直接交易的,谁也没法保证商家真的发货了,也没法保证用户真的付款了。解决这一困境,互联网创造了第三方支付这个媒介,第三方给用户担保:商家发货了,第三方给商家担保:用户付款了,从而保障整个交易能够进行。

网络通信双方的认证也是如此,通过两边都信赖的第三方认证(也即CA机构,下文中混用的第三方认证和CA机构是一个理解哈)来维系通信双方的信任。

  • 服务器端将自己的企业信息和公钥发送给第三方CA机构;

  • CA机构核对企业信息真实后,给企业所在服务器端颁发认证证书,以此证书来证明服务器端的公钥是真实可信的;

  • 服务器端将公钥和CA机构颁布的认证证书都发送给客户端,来自证清白;

  • 客户端拿到证书后,和CA机构确认证书真伪;

  • CA机构予以确认答复后,客户端即认为该服务器端是真实可信的,开始使用该服务器端的公钥进行后续交互。

在这里插入图片描述

实际上,也有客户端证书的,不错,就是用来证明客户端是真实可信的客户端。目前唐叔了解到的就登录网银时会要求用户确认ID和密码的同时也要求用户的客户端证书,不过用的场景少且特殊,这里就不作展开了。

✍️ CA机构的认证原理

上述服务器和CA机构的证书交互,以及客户端和CA机构的交互,涉及到第三方认证的私钥签名和公钥验签。

正如前面可逆加密算法章节提及,签名&验签,并不是为了加密,而是为了 “防伪”

  • 签名流程:
  1. 对原始消息做哈希,得到固定长度 H = Hash(M),即 摘要

  2. 用私钥对 H 做数学变换得到 S = Sign(H, sk),即 签名

  3. SM 一起发给对端(或直接发 S 让对方自己拿 M)。

  • 验签流程:
  1. 用公钥对 S 做逆运算,还原出 H'

  2. 本地计算 Hash(M) 得到 H

  3. H == H' 则验签通过。

具体到服务器、客户端和第三方认证的交互流程是这样的:

  1. 服务器端发送公钥给CA机构;

  2. CA机构使用自己的一组公钥私钥中的私钥,对服务器公钥进行签名,生成证书;

  3. CA机构将证书和服务器端公钥一并回传给服务器端;

  4. 服务器端将自身公钥和CA机构认证签名后的证书一并发送客户端;

  5. 客户端获取CA机构的公钥;

  6. 客户端使用CA机构的公钥对证书真伪进行验签,验签结果和服务器公钥比对,比对一致即验签通过。

(PS:这里有点忘了是直接比对,还是比对服务器公钥通过哈希函数生成的摘要了,不过大体类似吧,不要在意细节,2333~)

在这里插入图片描述

需要说明:这里第五步,获取第三方认证的公钥,实际上用户是无感知的,因为浏览器厂商已经内置了大多数第三方认证机构的公钥证书。

PS:虽然公钥和私钥是成对且唯一的,但是公钥的存储形式是多样的,如PEM文件公钥、DER文件公钥甚至将公钥并入其他如X.509证书等。所以看到浏览器的证书,其实大体也可以认为是公钥啦。

在这里插入图片描述

其实用户也可以使用OpenSSL开源程序自定义证书并导入浏览器的,即自签名证书。只是该类证书在浏览器可能被标识为"无法确认连接安全性"或"该网站的安全证书存在问题"。这里也不作展开介绍啦。

🛡️ 加固3:完整性校验

针对HTTP的第三宗罪,HTTPS采用消息认证码(MAC)的方式,来保障数据完整性,鉴别是否被篡改。

MAC核心机制就两个环节,生成MAC&校验MAC。

  1. 生成MAC
    在TLS握手阶段,客户端与服务器协商出对称会话密钥。每次发送数据前,使用该密钥+数据内容计算HMAC(如HMAC-SHA256),生成固定长度的校验值,并随数据包发送给接收方。

    有关TLS握手阶段,后文会进行展开介绍。

  2. 校验MAC
    接收方用相同密钥重新计算HMAC,与数据包附带的MAC比对。若不一致,则数据被篡改,直接丢弃。

在这里插入图片描述

PS:实际可以简单的认为HMAC就是对数据做哈希运算生成的哈希值,相同数据哈希值一样,不同数据哈希值是不一样的,因而通过这个可以来确认是否数据被篡改过。

五、HTTP + SSL/TLS = HTTPS

上面第四章节介绍的内容,其实就是 SSL/TLS 在干的事情。可以简单的理解,HTTPS协议其实是HTTP协议的通信传输部分采用了SSL或TLS进行替代,其他HTTP协议的内容并没有改变。PS:SSL和TLS是两个东西,TLS可以简单理解是SSL的进阶版本,但是核心机制是一样的。

在这里插入图片描述

下述是使用抓包工具抓取的HTTPS请求的数据情况,此时抓取的不再是HTTP流数据,而是TLS流数据。相当于HTTP和TLS交互,TLS和TCP交互,而不是HTTP直接和TCP交互。

在这里插入图片描述

其实,严格说SSL/TLS并不是HTTPS协议专有,也可以用于其他应用层协议的数据传输安全保障,如 SMTPTelnet 协议等。

最后让我们来详细拆解下HTTPS协议下客户端和服务器的交互流程吧。

  1. 开始SSL握手,客户端通过发送 Client Hello 报文。报文含客户端支持的 SSL的指定版本、加密组件列表。

  2. 服务器支持 SSL通信时,会以 Server Hello 报文作为应答。和客户端一样,在报文中包含 SSL版本以及加密组件。不过服务器的加密组件内容是从接收到的客户端加密组件内筛选出来的

  3. 之后服务器发送 Certificate 报文。报文中包含公开密钥证书。

  4. 最后服务器发送 Server Hello Done 报文通知客户端,最初阶段的 SSL握手协商部分结束。

  5. SSL第一次握手结束之后,客户端以 Client Key Exchange 报文作为回应。报文中包含通信加密中使用的一种被称为 Pre-master secret 的随机密码串。该报文已用步骤 3 中的公开密钥进行加密。

  6. 接着客户端继续发送 Change Cipher Spec 报文。该报文会提示服务器,在此报文之后的通信会采用 Pre-master secret 密钥加密,即对称加密算法进行加密传输。

  7. 客户端发送 Finished 报文。该报文包含连接至今全部报文的整体校验值。这次SSL握手是否能够成功,就看此时服务器是否能够正确解密该报文了。

  8. 服务器同样发送 Change Cipher Spec 报文。

  9. 服务器同样发送 Finished 报文。

  10. 服务器和客户端的 Finished 报文交换完毕之后,SSL连接就算建立完成。当然,通信会受到 SSL的保护。

  11. 从此处开始进行应用层协议的通信,即发送 HTTP 请求。

  12. 应用层协议通信,即发送 HTTP 响应。

  13. 最后由客户端断开连接。断开连接时,发送 close_notify 报文。下图做了一些省略,这步之后再发送 TCP FIN 报文来关闭与 TCP的通信,即TCP四次挥手。

在这里插入图片描述

好啦,以上就是本期的全部内容啦,花了周末两天时间,洋洋洒洒码了一万字,终于搞完啦,退啦退啦。


参考资料


网站公告

今日签到

点亮在社区的每一天
去签到