Caloogy 文章
English

签名之后再核对一遍

日期
2026 年 2 月 9 日
系列
钱包
阅读
3 分钟
主题
VerificationRead after writeReconciliationEthereum

一句话版本

你在界面上确认了"转 100 USDC 给 Alice",钱包签名并广播了一笔交易。但链上那笔交易真的是你确认的那笔吗?中间经过了网页、浏览器扩展、钱包软件,任何一环被篡改,签出去的都可能是另一笔。 "签名后核对"的做法是:拿到交易哈希后,从链上把这笔交易读回来,和当初的意图逐字段比对。不一致就立刻告警、锁定会话。这是"写完再读一遍"(read-after-write)这条古老工程原则在区块链上的应用。

全文分三层:

  1. 通俗理解:寄出去的信,再拆开看一遍
  2. 实际用处:数据库、支付对账、区块链交易
  3. 原理与工程要点:比对哪些字段、哪些差异可以接受、发现不一致之后怎么办

第一层:通俗理解

1.1 寄出去的信,再拆开看一遍

你让秘书帮你寄一封重要的信。秘书封好寄出了。你怎么知道他寄出的就是你写的那封?

如果你能从邮局那里把寄出的信调出来看一眼,就能确认。区块链恰好提供了这个能力:所有交易都是公开的,任何人都能按交易哈希把它读出来。

1.2 为什么不能只看签名前的界面

环节 可能出的问题
网页 被篡改,显示 A 地址,实际请求钱包签 B 地址
浏览器扩展 恶意扩展拦截并修改钱包请求
钱包软件 被替换成恶意版本
用户自己 在钱包弹窗里改了参数(比如手续费),或者点错了

签名前的核对,核对的是"界面上显示的东西";签名后的核对,核对的是"真正上链的东西"。


第二层:实际用处

Caloogy Wallet 也采用了广播后比对。


第三层:原理与工程要点

3.1 比对哪些字段

字段 必须一致 说明
from 是 从哪个地址发出
to 是 对 ERC-20 转账,这里是代币合约地址
value 是 转出的 ETH 数量
input(calldata) 是 对 ERC-20 转账,真正的收款人和金额编码在这里
chainId 是 防止签到了另一条链(见《签名登录与防重放》)
gas 相关字段 允许在一定范围内不同 钱包通常允许用户调整手续费

注意第 4 项:ERC-20 转账时,to 是代币合约,真正的收款人藏在 calldata 里。只比对 to 会漏掉最关键的篡改。

3.2 哪些差异可以接受

钱包允许用户修改手续费,所以 maxFeePerGas、maxPriorityFeePerGas、gasLimit 不一致是正常的。但应当设一个上限:手续费被改到意图的好几倍,也应该视为异常(可能是"用天价手续费掏空余额"的攻击,或者只是用户误操作,都值得提醒)。

3.3 发现不一致之后

不一致说明签名链路上至少有一环不可信,处理要果断:

  1. 立即把这笔意图标记为异常;
  2. 结束当前会话,要求重新认证;
  3. 通过独立渠道(邮件、站内通知)发出高优先级告警;
  4. 记入审计日志(见《哈希链审计日志》)。

此时交易很可能已经上链,追不回来。签名后核对的价值不在于挽回这一笔,而在于:

3.4 追踪交易的后续状态

交易广播后还可能出现几种情况,也都要跟踪:

状态 说明
已上链 读收据,确认执行成功(没有 revert)
长时间未上链 可能手续费太低,或者被丢弃
被替换 同一个 nonce 上出现了另一笔交易。可能是用户自己加速或取消,也可能是有人拿到了私钥抢先发了一笔

"被替换"尤其值得警惕:如果用户没有做过加速或取消操作,同一个 nonce 却出现了另一笔交易,几乎可以肯定私钥已经泄露。

3.5 和"签名前核对"是互补的

签名前核对 签名后核对
核对对象 界面显示的内容、模拟结果 链上实际的交易
能否阻止损失 能 通常不能(已上链)
能否发现链路被篡改 不能(篡改者控制了界面) 能

两者缺一不可。


总结

层次 要点
直觉 寄出的信再拆开看一遍
原则 read-after-write;对账
字段 from、to、value、input、chainId 必须一致;gas 有上限的容差
价值 发现链路被攻破、阻止下一笔、留下证据