news 2026/9/24 8:30:30

TLS + Web API 安全 · 01 · TLS 原理与握手

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TLS + Web API 安全 · 01 · TLS 原理与握手

一、先看问题:HTTP 是"明信片"

HTTP(超文本传输协议)是浏览器和网站之间说话的语言。它的特点就一个字:明文

也就是说,你发出去的内容,在网络上经过的每一台设备(路由器、交换机、Wi-Fi 热点、运营商)都能直接看到原文

我们亲手抓一次包看看。在远端执行:

cd /opt/tls-api-labs # 在后台抓 lo(本地回环网卡)上 8081 端口的流量,写到 /tmp/plain.txt timeout 6 tcpdump -i lo -A -s0 "port 8081" > /tmp/plain.txt 2>/dev/null & ​ # 等抓包起来后,用 HTTP 明文登录一次 sleep 1 curl -s http://127.0.0.1:8081/api/login -H "Content-Type: application/json" -d '{"username":"alice","password":"password1"}' >/dev/null ​ sleep 6 grep -aE "POST|username|password|Host:" /tmp/plain.txt | head

真实回显:

账号密码是裸奔的。抓包工具(tcpdump、Wireshark)不需要任何密钥,直接把明文打印出来了。

命令逐参数解释:

  • tcpdumpLinux 上最常用的抓包工具,能把网卡上流过的数据包"抄"下来。

  • -i lo-i指定网卡(interface)。lo是"本地回环网卡"(loopback),本机进程之间通信走它。我们要抓的是本机发往本机的请求,所以用lo

  • -A:以 ASCII 文本形式显示包内容,这样明文 HTTP 能直接读出来。

  • -s0-s指定每个包最多抓多少字节(snaplen),0表示"不限制,整个包都抓"。老版本 tcpdump 默认只抓几十字节(如 68),会截断应用层内容,所以要写-s0

  • "port 8081":过滤条件,只抓 8081 端口的流量(port表示端口)。不过滤的话会抓到一堆无关流量。

  • >:把输出重定向到文件。

  • 2>/dev/null:把错误信息丢掉(不显示)。

  • 结尾的&:放到后台运行,不阻塞当前终端。

  • timeout 6 ...:6 秒后自动结束,免得它一直抓着。


二、TLS 要同时解决三个问题

HTTPS = HTTP + TLS。TLS(Transport Layer Security,传输层安全)在 HTTP 之下、TCP 之上,给数据套了一个"加密管道"。

它必须同时解决三个问题,缺一不可:

问题专业名词攻击者能做什么TLS 怎么解决
别人能偷看机密性(Confidentiality)窃听密码、聊天记录加密
别人能偷偷改完整性(Integrity)篡改转账金额、注入恶意内容消息认证码 / 签名
别人能冒充网站身份认证(Authentication)假基站、假 Wi-Fi、DNS 劫持到钓鱼站数字证书

只加密不就行了,为什么还要"完整性"和"身份认证"?

假设只有加密:攻击者虽然看不懂内容,但可以把密文乱改一通,让你解出来一堆乱码(这叫"篡改")。

再假设只有加密和完整性:攻击者可以直接冒充你连接的服务器——因为客户端根本不知道对面是谁,攻击者用自己的密钥和客户端"加密聊天",客户端还蒙在鼓里。所以三者必须一起上。


三、密码学地基

3.1 对称加密:一把钥匙,锁和开都用它

是什么:加密和解密用同一把密钥。典型算法:AES。

打个比方:一个带锁的保险箱,你用钥匙锁上,对方用同一把钥匙打开。

优点。适合加密大量数据(比如整个网页)。

致命弱点:密钥怎么安全地给对方?你俩如果从没见过面,你怎么把钥匙交给他?直接把钥匙发过去,路上被偷了怎么办?这就是"密钥分发问题"。

在 TLS 里,对称加密用来加密真正的业务数据,因为快。但钥匙的协商要靠下面的非对称加密。

3.2 非对称加密:公钥和私钥,一对钥匙

是什么:一次生成一对密钥:

  • 公钥(public key):可以随便公开,谁都能拿到。

  • 私钥(private key):只有自己保管,绝不外泄。

规则很神奇:

  • 公钥加密的东西,只有对应的私钥能解开。

  • 私钥签名的东西,用对应的公钥能验证(见 3.5)。

打个比方:公钥像一个"投递口",谁都能往里塞信;私钥像"信箱钥匙",只有主人能打开取信。

优点:解决了密钥分发问题——公钥可以公开传,不怕被偷。

弱点(比对称加密慢几百上千倍),不适合加密大量数据。

TLS 的聪明之处:用非对称加密,只协商出一把对称密钥;之后所有数据都用对称加密。这样既安全又快。

3.3 哈希:数据的"指纹"

是什么:把任意长度的数据,算成一个固定长度的短字符串(摘要)。典型算法:SHA-256(固定 32 字节)。

特点

  • 单向:能从数据算出指纹,但无法从指纹反推出数据。

  • 敏感:数据改一个字节,指纹就完全不同。

  • 抗碰撞:几乎不可能找到两个不同数据有相同指纹。

用途:校验数据有没有被改(比对指纹)、存密码(存指纹而不是明文)。

注意:哈希本身不能证明"是谁",因为它不需要密钥,任何人都能算。要防篡改,还得加"密钥",于是有了 HMAC。

3.4 HMAC:带密钥的哈希(消息认证码)

是什么:HMAC = Hash + 一把共享密钥。双方都有同一把密钥,发送方算一个"带密钥的指纹",接收方用同样的密钥再算一遍,一致就说明没被改,且确实是拿着密钥的人发的

解决了什么:完整性 + "来源可信"。攻击者没有密钥,改不了数据还伪造不出新指纹。

弱点:要求双方事先共享同一把密钥(又回到密钥分发问题)。所以 HMAC 常用在"已经通过别的方式建立了共享密钥"之后。

JWT 里的HS256就是 HMAC-SHA256。后面第 05 篇会大量用到。

3.5 数字签名:私钥签,公钥验

是什么:发送方用自己的私钥对数据的哈希值"签名";任何人用发送方的公钥都能验证这个签名。

它证明了什么

  1. 身份:只有私钥持有者能签出这个名 → 说明确实是"他"发的。

  2. 完整性:数据被改了,签名就验不过。

和 HMAC 的区别:HMAC 双方共享一把密钥(对称);数字签名用私钥签、公钥验(非对称),所以不需要共享密钥,而且能向第三方证明"是谁签的"。

弱点你得先确认"这把公钥真的是他的"。否则攻击者可以拿自己的公钥冒充,说"我是银行"。这个"确认公钥归属"的问题,就由数字证书来解决(第 02 篇整篇讲它)。

3.6 小结:TLS 的"组合拳"

把上面五样拼起来,就是 TLS 的核心思想:

1. 服务器把「公钥」放进一张「证书」,证书由权威 CA 签名 → 解决"公钥是谁的" 2. 客户端验证证书,拿到可信的服务器公钥 → 身份认证 3. 双方用非对称加密/密钥交换,协商出一把「对称会话密钥」 → 解决"密钥分发" 4. 之后所有数据用「对称加密」传,并用「MAC/签名」保证完整性 → 又快又安全

一句话:用非对称的方式,安全地商量出一把对称钥匙;然后用这把对称钥匙快速加密后面的所有对话。


四、TLS 1.2 握手:一次完整的"相亲"

"握手(handshake)"指正式传数据之前,双方先协商好"用什么加密、密钥是多少、你是谁"。TLS 1.2 需要2 个 RTT(RTT = Round Trip Time,一次"一去一回"的网络耗时)。

下面是 TLS 1.2 的完整流程(表示客户端发,表示服务器发):

客户端 服务器 │ │ │ ──① ClientHello ─────────────────────────────>│ 我支持的 TLS 版本、加密套件、一个随机数 │ │ │ <─② ServerHello ───────────────────────────── │ 选定的版本、套件、另一个随机数 │ <─③ Certificate ───────────────────────────── │ 服务器证书(含公钥) │ <─④ ServerKeyExchange ─────────────────────── │ 密钥交换参数(如 ECDHE 的公钥)+ 签名 │ <─⑤ ServerHelloDone ───────────────────────── │ 我说完了 │ │ │ ──⑥ ClientKeyExchange ───────────────────────>│ 客户端的密钥交换参数 │ ──⑦ ChangeCipherSpec ────────────────────────>│ 接下来我发的都加密了 │ ──⑧ Finished(加密)─────────────────────────> │ 握手校验值 │ │ │ <─⑨ ChangeCipherSpec ──────────────────────── │ │ <─⑩ Finished(加密)───────────────────────── │ │ │ │ ══════ 之后全是加密的应用数据(HTTP)══════════ │

逐步解释每一步为什么需要

  • ① ClientHello:客户端先说"我支持哪些 TLS 版本、哪些加密套件(cipher suites),外加一个随机数"。这个随机数是后面生成密钥的原料之一,每次连接都不一样,保证密钥不重复。

  • ② ServerHello:服务器从客户端给的清单里挑一个版本和套件,再给一个自己的随机数。

  • ③ Certificate:服务器把证书发过来。客户端用内置的 CA 公钥验证它,从而确信"这把公钥属于我要访问的网站"

  • ④ ServerKeyExchange:如果用的是 ECDHE 这类密钥交换算法,服务器在这里给出密钥交换需要的参数,并用私钥签名,防止被人中间篡改。

  • ⑤ ServerHelloDone:告诉客户端"我这边说完了"。

  • ⑥ ClientKeyExchange:客户端给出自己那半份密钥交换参数。至此双方各自都能算出一个共享的"预主密钥"。

  • ⑦⑧:客户端发 ChangeCipherSpec 说"接下来加密",然后发一个 Finished(把前面所有握手内容的摘要加密发过去)——对方一验证,就知道前面的握手有没有被篡改

  • ⑨⑩:服务器同样回应。

为什么是 2-RTT?因为客户端要等服务器把 Hello 相关的东西发完(第 1 个 RTT),再把自己的密钥交换参数和 Finished 发过去(第 2 个 RTT)。多一个来回,就多一次延迟。

密钥是怎么算出来的?双方各自贡献一个随机数(ClientHello 的 + ServerHello 的),再加上密钥交换算出的"预主密钥",三者一起经过一轮推导,得到最终的对称会话密钥。这样任何一方都无法单独决定密钥,更安全。

为什么不直接让客户端生成一个密钥,用服务器公钥加密发过去?

老式 RSA 密钥交换就是这么做的。但它有个大问题:没有前向保密。如果攻击者今天把你服务器的私钥偷走了,他就能解密过去所有被录下来的流量(因为当时的会话密钥是用那个私钥保护发出去的)。现代 TLS 改用 ECDHE(临时密钥交换),每次会话临时生成密钥,用完就扔——即使服务器私钥将来泄露,也解不开过去的流量。这叫前向保密(PFS)


五、TLS 1.3 握手:1-RTT,更快也更安全

TLS 1.3 做了两件大事:

  1. 更快:正常握手只要1-RTT(甚至支持 0-RTT)。

  2. 更安全:砍掉所有已知有问题的老算法,强制前向保密,把更多握手内容也加密。

TLS 1.3 之所以能 1-RTT,是因为它假设双方会选 ECDHE,于是客户端在第一个 ClientHello 里就把密钥交换参数(key_share)一起发过去了,省掉了一个来回。而且从 ServerHello 之后的内容(包括证书)都是加密的,中间人连你用的什么证书都看不到。

我们来真实跑一次,看服务器实际选了什么。在远端执行:

cd /opt/tls-api-labs openssl s_client -connect 127.0.0.1:443 -servername api.lab -CAfile ca/ca.crt -tls1_3 -brief </dev/null

真实回显:

Connecting to 127.0.0.1 CONNECTION ESTABLISHED Protocol version: TLSv1.3 Ciphersuite: TLS_AES_256_GCM_SHA384 Peer certificate: C=CN, O=TLS-API Lab, CN=api.lab Hash used: SHA256 Signature type: rsa_pss_rsae_sha256 Verification: OK Negotiated TLS1.3 group: X25519MLKEM768 DONE

命令逐参数解释:

  • openssl s_client:OpenSSL 自带的"TLS 客户端"工具,用来手动建立一次 TLS 连接并打印握手细节。

  • -connect 127.0.0.1:443:连到哪个地址和端口(地址:端口)。

  • -servername api.lab:设置SNI(Server Name Indication)。SNI 是客户端在握手时告诉服务器"我要访问哪个域名"。一台服务器可能用同一个 IP 托管多个网站,靠 SNI 决定出示哪张证书。没有它,服务器可能给你错误的证书。

  • -CAfile ca/ca.crt:告诉客户端"用这个 CA 证书来验证服务器"。相当于把我们的自签 CA 临时"信任"一下。

  • -tls1_3:强制只用 TLS 1.3。对比用-tls1_2

  • -brief:只打印一行行摘要,不然会输出一大坨。

  • </dev/null:把标准输入接到"空设备"。因为s_client连上后会等你输入内容发给服务器,我们只想看握手,不想交互,所以喂个空输入让它自己结束。

怎么看回显

  • Protocol version: TLSv1.3:最终协商出来的版本。

  • Ciphersuite: TLS_AES_256_GCM_SHA384:加密套件。拆开看:TLS+AES_256_GCM(用 AES-256 对称加密,GCM 模式)+SHA384(用 SHA-384 做完整性校验)。

  • Peer certificate: ... CN=api.lab:服务器出示的证书。

  • Verification: OK:证书验证通过了(因为我们-CAfile信任了它签发的 CA)。

  • Negotiated TLS1.3 group: X25519MLKEM768:密钥交换用的算法组。这是一个后量子混合算法(X25519 + ML-KEM-768),是较新 OpenSSL 的默认。这说明TLS 的算法一直在演进

再对比 TLS 1.2:

openssl s_client -connect 127.0.0.1:443 -servername api.lab -CAfile ca/ca.crt -tls1_2 -brief </dev/null

真实回显:

Protocol version: TLSv1.2 Ciphersuite: ECDHE-RSA-AES256-GCM-SHA384 ... Peer Temp Key: X25519, 253 bits

ECDHE-RSA-AES256-GCM-SHA384拆开看:ECDHE(临时椭圆曲线密钥交换,提供前向保密)+RSA(用 RSA 证书签名做身份认证)+AES256-GCM(对称加密)+SHA384(完整性)。

0-RTT 是什么?

TLS 1.3 还支持0-RTT:如果客户端之前连过这个服务器,它可以在第一个包里就带上加密的应用数据,零个来回。代价是:0-RTT 的数据可能被攻击者录制后重放(因为不含新的随机数协商)。所以只有幂等、安全的请求(如 GET)才适合 0-RTT,涉及转账、下单这种绝不能重复的请求不要用。


六、前向保密(PFS)

定义:即使服务器的长期私钥将来泄露了,攻击者也无法解密过去录下来的历史流量

为什么重要:攻击者常常"先录流量、后偷密钥"(先把加密流量存着,等哪天攻破服务器拿到私钥再解密)。没有前向保密的话,这一天到来时,所有历史流量全暴露。

怎么实现:用 ECDHE(每次会话临时生成一对密钥,会话结束就丢弃)。会话密钥不依赖长期私钥,所以长期私钥泄露也没用。

TLS 1.3 强制要求前向保密(不再支持纯 RSA 密钥交换),这是它比 1.2 更安全的重要原因之一。


七、现实世界:TLS 到底在哪里"终止"

现实中,TLS 不一定是你的后端应用在管。常见架构:

场景TLS 在哪终止说明
小型网站nginx / Apache就是本实验的做法:nginx 负责握手,再把明文转给后端
大厂负载均衡 / CDN用户的 TLS 在 CDN 边缘节点终止,CDN 到源站可能再套一层 TLS
云服务云负载均衡 / API 网关证书上传到云平台,平台统一管理
微服务内部服务网格(mTLS)服务之间互相也要证书,双向认证

"TLS 终止"(TLS termination)的意思是:加密在这里被解开,之后到后端就是明文了。所以:

  • 公网那段是加密的(用户 ↔ nginx/CDN)。

  • 内网那段可能又是明文(nginx ↔ 后端),也可能再加密。

本实验就是"nginx 终止 TLS,后端127.0.0.1:9443是明文"——这是最常见的部署方式,也方便你在 nginx 后面看明文。

ALPN:握手时客户端还会告诉服务器"我支持 HTTP/2 还是 HTTP/1.1",这叫 ALPN(应用层协议协商)。用 curl-v能看到:

* ALPN: curl offers h2,http/1.1 * ALPN: server accepted http/1.1

八、本篇小结

  1. HTTP 是明文,抓包直接看到账号密码;TLS 给它套上加密管道。

  2. TLS 同时解决机密性、完整性、身份认证三件事。

  3. 五种密码学工具:对称加密(快,但密钥分发难)、非对称加密(解决分发,但慢)、哈希(指纹)、HMAC(带密钥的指纹)、数字签名(私钥签公钥验)。

  4. TLS 的组合拳:用非对称安全地协商出一把对称密钥,之后用对称加密传数据

  5. TLS 1.2 是 2-RTT;TLS 1.3 是 1-RTT,砍掉弱算法、强制前向保密、加密更多握手内容。

  6. 前向保密:长期私钥泄露也解不开历史流量。

  7. 现实里 TLS 常在 nginx/CDN/负载均衡处终止,之后到后端可能是明文。


九、总结

  1. TLS 要解决哪三个问题?各用什么手段?

    机密性(对称加密)、完整性(HMAC/签名)、身份认证(数字证书)。三者必须同时满足,少一个都会被攻击者利用。

  2. 对称加密和非对称加密各自的优缺点是什么?TLS 为什么两个都用?

    :对称加密,适合加密大量数据,但密钥分发难(怎么安全地把同一把钥匙给对方);非对称加密解决了分发(公钥可公开),但。TLS 用非对称安全地协商出一把对称密钥,之后所有数据用对称加密——兼得安全与速度

  3. 哈希和 HMAC 的区别是什么?为什么哈希本身不能防篡改?

    :哈希不需要密钥,任何人都会算,只能验证"数据有没有变";HMAC 是"哈希 + 共享密钥",还能证明"是拿着密钥的人发的"。因为哈希谁都能算,攻击者改了数据后可以自己重算一个哈希替换掉,接收方照样验得过,所以哈希单独不能防篡改。

  4. TLS 1.3 为什么能比 1.2 少一个 RTT?它牺牲了什么换来了 0-RTT?

    :1.3假设双方会用 ECDHE,客户端在第一个 ClientHello 里就把密钥交换参数(key_share)一起发过去,省掉一个来回,所以只要 1-RTT。0-RTT 是"客户端在第一个包里就带应用数据",代价是这些数据缺少新的随机数协商,可能被攻击者录制后重放——所以只适合幂等、安全的请求(如 GET)。

  5. "前向保密"是什么意思?没有它会发生什么?

    :前向保密(PFS)=即使服务器的长期私钥将来泄露,也解不开过去录下来的历史流量。实现方式是 ECDHE(每次会话临时生成密钥,用完即弃)。没有它,攻击者可以"先录流量、后偷私钥",等拿到私钥那天把历史流量全部解密。

  6. SNI 是干什么用的?没有它可能出现什么问题?

    :SNI 让客户端在握手时告诉服务器"我要访问哪个域名"。一台服务器(一个 IP)可能托管多个网站,靠 SNI 决定出示哪张证书。没有它,服务器可能返回默认站点/错误的证书,导致证书校验失败或访问到错误的网站。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 8:24:16

激光二极管恒流驱动设计核心:精度、热管理与环路稳定性

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/24 8:19:42

高精度温度采集实战:GD32F30x驱动CS1237测量PT1000

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/24 8:17:11

ZYNQ裸机lwIP UDP回环工程详解:Vitis配置与Cache一致性实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/24 8:05:18

EmDash 插件开发实战:深入 Block Kit 声明式 UI 体系

CMS后端前端插件系统 【免费下载链接】emdash EmDash is a full-stack TypeScript CMS based on Astro; the spiritual successor to WordPress 项目地址&#xff1a; https://gitcode.com/gh_mirrors/emdas/emdash 点击查看 免费下载 Block Kit 是 EmDash CMS&#xff08;基于…

作者头像 李华