钱包弹出的结构化签名窗口:域名信息四行到底在防什么 图 1
钱包弹出的结构化签名窗口:域名信息四行到底在防什么 · 图 1

钱包让你签一种叫“结构化数据”的内容时,弹窗通常比 Sign Message 复杂得多:一段带字段名的数据,顶上还有几行叫域名信息的东西。这套机制出自 EIP-712,叫 eth_signTypedData。多数教程只教你“看清内容再签”,但真正值得逐项读的是那几行域信息——它们决定了这笔签名能被拿到哪里去用。

为什么要有结构签名而不只是签文本

签任意文本(Sign Message)的问题在于,你签的哈希背后没有语义边界:一段“我确认登录”的文字哈希,理论上可以被拿到别的场合重放。EIP-712 的思路是把数据和类型定义一起哈希:最终签名的输入是固定前缀 0x19 0x01、域分隔符和消息结构哈希三段拼接。域分隔符由域名信息算出,等于给签名加了一层“只在某某链、某某合约、某某版本下有效”的封印,跨链、跨合约拿去重放时哈希就对不上了。

域名信息四行逐项读

域名信息一般由四个字段组成。verifyingContract 是声明“将来由哪个合约来验证这笔签名”的地址,这是四行里唯一的链上事实,可以去区块浏览器按地址核对它是否真是你说得出的那个合约。chainId 是链标识,作用是把签名锁死在这条链上,防止同一份数据在另一条同地址账户的链上被使用,核对方法和网络配置单里的链标识一致。nameversion 则要小心:它们是发起方自己填的字符串,合约按 ERC-5267 一类接口对外声明时才会与链上校验挂钩,仅在弹窗里出现时只是网站自称,钓鱼站同样可以填主流协议的名字。所以四行里的可信度排序是:先核 verifyingContract,再看 chainId 与当前网络是否一致,最后把 nameversion 当作未经证实的宣传语。

消息正文里最常藏风险的字段

正文常见 deadline(截止时间戳)和 nonce(防重放编号)。deadline 决定这笔授权过期前一直有人能替你执行,遇到填成几年后甚至留空的要警惕;合约实现不规范时也可能根本没有 deadline 字段,这时更要确认用途一次性。金额类字段用的是最小单位整数,读之前先回忆该代币小数位,避免把 1000000 看成 100 万枚却实际是一枚。还有一个容易忽略的字段是签名者地址本身:正文里若出现一个“from”字段而它并不等于你的当前账户,说明这份数据在替你替别人背书,正常协议不会这样要求。

弹窗显示不全时怎么处理

部分钱包对超长结构化数据做折叠或截断显示,只露出前几个字段。显示不全就按盲签处理:不要靠猜补全你没看到的字段。稳妥做法是放弃这次授权流程,换一个能完整展开各层结构的钱包环境重走一遍;如果协议官方文档提供了本地重算或查看类型的途径,先按文档核对再决定。另外记住一个边界:域分隔符提供的防重放只在“正确实现了这套校验的合约”之间成立——恶意合约验证签名时可以不看域信息,所以域字段保护的是“同一份签名被别的正经合约复用”,它替你挡的是跨链跨协议重放,挡不住“你正在把签名交给一个坏合约”这件事,后者只能靠核对 verifyingContract

操作顺序建议

① 核对 verifyingContract 与官方文档或浏览器“已验证合约”一致;② 核对网络与 chainId;③ 读正文的授权对象、额度、deadline;④ 读不懂类型定义时按盲签对待,宁可不签。这条顺序的依据来自机制本身:域字段里只有合约地址有链上锚点,先做唯一能做实的核对,再处理可伪装的声明字段,最后才读业务内容——顺序反了,很容易被一个真实的项目名带着跳过地址核对。想先弄清“签文本”这一层,可看 钱包“签署消息”是什么?站点让你 Sign Message 前必须核对什么

风险提示:签名本身不上链也不转币,但签名内容可能被广播上链执行,涉及代币授权与资产转移。本文为安全科普,不构成任何投资建议。