Caloogy 文章
English

盲签与"所见即所签"

日期
2025 年 7 月 25 日
系列
钱包
阅读
3 分钟
主题
Blind signingEip 712PermitPermit2

一句话版本

签名是加密货币世界里唯一的"授权"动作:私钥一签,链上就认。所以签名前最重要的问题是:我到底在签什么? "盲签"就是签一串自己看不懂的数据,等于在空白支票上签名。今天占比最高的盗币手法 Permit / Permit2 签名钓鱼,就是让用户以为自己在"登录"或"领空投",实际签下的是"允许某人转走我的代币"。防御的核心原则叫所见即所签(What You See Is What You Sign):钱包必须能把签名内容完整解码、用人话展示,解码不了就不签。

全文分三层:

  1. 通俗理解:空白支票
  2. 实际用处:Permit 钓鱼、Bybit 事件、硬件钱包的"清晰签名"
  3. 原理与工程要点:eth_sign、personal_sign、EIP-712、Permit 的结构

第一层:通俗理解

1.1 空白支票

有人递给你一张纸,上面是一串乱码:"0x8f3a...e21c,请签名确认。"你签了。

后来才知道,这串乱码翻译过来是:"本人同意,把我账户里所有 USDC 的转出权交给 0xBad...。"

这就是盲签。签名算法本身毫无问题,问题是你不知道自己签了什么。

1.2 链下签名为什么更危险

很多人以为"只要不发交易、不花 gas,就没有风险"。但有一类签名不上链、不花钱,却能被别人拿去上链执行:

整个过程你的钱包里没有出现过任何一笔交易请求,只有一次"签名"。


第二层:实际用处

Caloogy Wallet 也采用了"只签可完整解码的内容"的原则,并禁用了危险的签名方法。


第三层:原理与工程要点

3.1 以太坊的几种签名方法

方法 签的是什么 风险
eth_sign 任意 32 字节哈希 最高:这个哈希可能就是一笔交易的哈希,用户完全无法辨认。主流钱包已默认禁用
personal_sign 加了固定前缀 "\x19Ethereum Signed Message:\n" + 长度 的消息 前缀保证它不可能是交易。签可读文本时安全;签裸十六进制时仍是盲签
eth_signTypedData_v4(EIP-712) 结构化数据,带 domain(应用名、链 ID、合约地址) 钱包可以解析展示,但用户必须真的读懂
eth_sendTransaction 一笔交易 钱包会展示 to、value、data,但 data 需要解码

3.2 EIP-712 的结构

{
  "domain": { "name": "USD Coin", "version": "2", "chainId": 1,
              "verifyingContract": "0xA0b8...eB48" },
  "primaryType": "Permit",
  "message": {
    "owner":   "0x你的地址",
    "spender": "0x攻击者地址",
    "value":   "115792089237316195423570985008687907853269984665640564039457584007913129639935",
    "nonce":   0,
    "deadline": 1893456000
  }
}

翻译成人话:"我允许 0x攻击者地址,从现在到 2030 年 1 月 1 日,花掉我所有的 USDC。"

其中 value 那个天文数字是 2256−12^{256} - 1,即"无限额"(见《无限额授权》)。签名之后,任何人都可以把这份签名提交给 USDC 合约的 permit 函数,链上就会记录这次授权;接着 spender 调用 transferFrom 就能把钱转走。

3.3 Permit2

Uniswap 推出的 Permit2 是一个通用授权合约:用户先对 Permit2 做一次(通常是无限额的)链上授权,以后各个应用都只需要用户签名就能动用代币。体验更好,但也意味着:一次被骗的签名,就能动用你授权给 Permit2 的全部代币。

3.4 "所见即所签"的工程原则

  1. 不支持 eth_sign,不对裸十六进制使用 personal_sign;
  2. 只签能完整解码的内容:交易的 calldata 要解析出函数名和参数,EIP-712 要识别出 spender、额度、期限;
  3. 解码不了就拒绝,而不是"显示原始数据让用户自己判断"(见《Fail-closed》);
  4. 对授权类签名显示最醒目的警告:"这等于把你的资产交给 X";
  5. 签名请求必须由用户的点击直接触发,页面加载时绝不自动弹出签名;
  6. 对多签钱包,签名人要能独立于网页(在硬件钱包屏幕上、或用另一套工具)解码交易,例如检查 operation 字段是否是危险的 delegatecall。

总结

层次 要点
直觉 盲签 = 在空白支票上签字
现实 链下签名不花 gas,却能被拿去上链转走资产
技术 禁用 eth_sign;EIP-712 可解析,但仍要读懂 spender 和额度
原则 所见即所签:解码不了就不签;硬件钱包清晰显示