密码学 38:结课一——解释并验证一次 HTTPS 订单请求
浏览器向 orders.test 提交一笔合成订单:order=demo-001;quantity=1。如果页面展示“TLS 连接安全”,是不是订单就绝不会重复执行,服务器也必然不会篡改履约结果?并不是。结课先把网络通道、请求应用认证和订单业务事实画到同一条链上,逐层设计能失败的验证。所谓“成功”必须能指向一次具体输入、秘密持有人、可核对输出和信任起点。
第一张图:握手的信任边界
客户端已有预期主机名 orders.test 和只交给这个实验客户端的临时 CA。服务端有对应叶证书及其私钥,握手时还协商临时密钥交换材料。证书链签名告诉客户端公钥由指定信任锚所授权的签发关系连接而来;检查 SAN 和用途才把服务端与预期主机名联系起来。TLS 1.3 的 CertificateVerify 以服务器证书对应私钥签握手摘要,Finished 用派生出的握手密钥认证前面的握手内容;证书 CA 签名、服务器握手签名与 Finished 各认证不同对象,不能缩成“服务器拿私钥加密订单”。
1 | |
本地组件 14_local_tls.py 用 Python 标准库 ssl/系统 OpenSSL 运行 TLS 1.3 回环服务;正确名字与显式 CA 能下单,错主机名及完全不传该 CA 都握手失败。证书私钥在临时目录生成并删除,不装进系统信任库。这个结果不包含真实浏览器证书 UI 的验收,也不构成公网 PKI 部署证明。
第二张图:阶段与方向决定谁能解订单
握手共享秘密不直接作为“所有消息共用密码”。TLS 按阶段、方向派生不同 traffic secret,然后在记录层使用确定的 AEAD 键及记录相关 nonce;重放保护和序号机制属于当前 TLS 连接内的记录处理,不是浏览器再次点击支付时的业务去重。抓住时序:在应用流量秘密生效之前不能用应用数据密钥去解握手消息;TLS 终止在代理时,代理能看到终止后的明文,代理到后端如果没有另行保护就不是浏览器端到端密文。
1 | |
记录层帮对端发现通信过程的未经授权修改和不合规记录顺序,但无法决定订单是否是用户打算提交、库存是否存在或重试是否算同一笔。本章实验没有提取/发布流量秘密,也不能声称捕获了浏览器真实抓包。
第三张图:应用请求的身份、字节与消费状态
在隔离的 23_order_api.py 中,客户端和订单服务共享一把临时 HMAC 密钥;客户端将请求方法、路径、Content-Type、时间戳、业务 nonce 与原始 body 按带长度的格式编码为确定字节,再做 HMAC。服务端从同一密钥算期望值,安全比较、检查时间窗口,然后将 nonce 记入单进程内存消费集合。HMAC 的持有人双方都能生成认证值,不是第三方可验证的数字签名;订单服务对业务数据的后续动作仍需单独治理。
1 | |
移除长度编码会让字段拼接可能发生歧义;移除时间窗口,旧请求在泄漏后可能长期有效;移除 nonce 消费,即使时间窗口内 HMAC 永远为真,同一订单可能重复执行。消费表必须按请求身份/目标原子持久化,真实多实例服务不能靠这个单进程集合保证幂等。真正浏览器网页通常不持有服务的 HMAC 共享秘密:这里的第二个端点是受控测试客户端,不是“浏览器拥有 HMAC 密钥”的模拟故事。
可执行的跨层检查与遗漏项
examples/cryptography/38_order_capstone.py 分别运行 14 与 23 两套真实本地 TLS 端点,汇总上述成功和失败观察。两套服务不是同一个长连接或同一份订单,不能说已经完成浏览器到订单后台端到端集成;它们只分别验收相应层的配置和消息。运行命令:
先按仓库内 examples/cryptography/README.md 完成环境准备;以下命令从仓库根目录执行。
1 | |
本地 1 项结课测试通过:真 TLS 1.3/目标服务名、错误证书名称、没有 CA、应用 body/route 篡改、过期及重复 nonce 等结果可失败。真实浏览器、DNS、代理后段、真实付款、库存、持久化幂等与订单交付仍 NOT_RUN。如果只看到 HTTP 200,就不能略掉证书错误或未执行的业务状态检查;如果证书握手成功,也不能从中推断付款已被账本确认。
两道练习及答案
画图题: 把客户端 CA、服务端证书私钥、握手临时秘密、TLS 双向 traffic secret、订单 HMAC 密钥、nonce 消费表分别填到三张图。若在 TLS 代理终止后让后端直连明文,在哪条连接上会失去传输保护?
答案: CA 是客户端信任输入;证书私钥在服务器,临时秘密分别由两端协商并派生双向密钥;HMAC 密钥在应用双方;消费表在服务端。代理结束浏览器的 TLS 后,浏览器与代理之间仍可加密,代理到后端是另一条连接,若它不使用受控网络/另建 TLS,后段明文可被观察或修改。浏览器一侧的锁标识不覆盖后段。
实验变更题: 调用 23_order_api.py 的 send 时将 body 改为另一金额但保持 signed_body 为原字节;另保留 body/MAC 而将原 nonce 再发一次。两种负例应分别在哪层拒绝?将本地 CA 改为系统不信任的 CA 后,应用 HMAC 检查还会被执行吗?
答案: 第一种是应用 HMAC 的内容不匹配,应按本地实现返回认证失败;第二种是 MAC 仍为真但 nonce 消费状态已存在,应拒重放。若 TLS 客户端无法验证服务器证书,不应发出请求,自然到不了后续 HMAC 检查;不能以“应用签名正确”为理由关闭服务端证书验证。
资料与衔接
- RFC 9846 TLS 1.3 · RFC 9525 服务身份核对 · RFC 2104 HMAC。实验 HMAC 格式自定义,不是 RFC 9421。
- 14:证书与信任链 · 15:TLS 1.3 握手 · 23:API 时间与消费状态。






