首页 / 授权、钓鱼与被盗急救 / 签名请求怎么读

签名请求怎么读:分清三类签名,看懂 Permit 的每个字段

同一个弹窗,可能装着三种完全不同的东西。它可能是一笔要上链、要你出 gas 的交易;可能是一段只用来证明「这个地址归我」的纯文本;也可能是一张签完就能被人拿去改你代币额度的凭证。在你眼里它们长得都像一块灰底白字的方框,在以太坊的规范里,这三样从第一个字节就已经分开了。本站另一篇文章里有一句要求:签名前一定看清你到底签了什么。这篇补的是那句话后面缺的方法——别人递给你一个签名请求,你该怎么一层层把它读开。

一个签名请求里可能装着哪三种东西

先把类型分清,后面的判断才有地方落脚。EIP-712 做的第一件事,是把「可以被私钥签的东西」从原来的两类扩成三类:交易、字节串(也就是纯文本消息),以及结构化数据。三者的编码方式写得很死:交易用 RLP;纯文本消息是固定前缀 "\x19Ethereum Signed Message:\n" 接上消息长度再接上消息本身;结构化数据是 "\x19\x01" 接上域分隔值再接上消息结构的哈希。写完这三行,原文补了一句关键的话:这套编码是单射的,因为三种情况在第一个字节上就不一样。

所以你面前这个请求属于哪一类,是协议层面已经定死的事,不是观感问题。三条路通向不同的后果:交易花你的 gas、立刻在链上留下痕迹;纯文本消息常被拿来证明「我持有这个地址」,不上链也不花 gas;结构化数据这一类最需要逐字段看,因为 Permit 这种改额度的东西走的正是这条路。顺带纠正一个很顽固的错觉——不花 gas 不等于没有后果,本站代币授权的风险与撤销提过这一点,这篇把它往下讲完。

你本来就该看得见字段,而不是一串 hex

EIP-712 的摘要把要解决的问题写得很直白:当时被签的消息是一串不透明的十六进制字符串,展示给用户时几乎不带任何上下文,用户看不出它由哪些东西组成;而它给出的方案,原文的说法是把数据连同结构一起编码,使其能够在签名时展示给用户核对。「弹窗里能看见字段名和取值」因此不是某个钱包做得贴心,而是这整套标准被提出来的目的本身。

反过来更有用:面前只有一串哈希、找不到任何字段名,说明要么这个请求走的不是结构化数据这条路,要么你手上这台设备没把结构解析出来。两种情况下你都不知道自己在签什么。圈子里管这种签法叫盲签,本文没有去核任何厂商对这个词的正式定义,所以只把它当成一个现象来说。

这里必须说明的一件事各家钱包 App 和硬件设备对结构化数据的解析能力、显示方式、会不会弹风险提示,差别很大。本文没有逐家去读它们的官方说明,所以不替任何一家描述界面或告警。你能看到多少,以你手上那台实际显示的为准;拿不准的时候,宁可当成看不到。

结构化数据先读两层:域,和主类型

确认是结构化数据之后,被签的内容由两部分拼起来:一个域分隔值,和消息结构本身的哈希。域这一层的字段名是写死的,ERC-2612 里逐字给出的写法是 EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)nameversion 说的是这条消息声称属于哪个应用或合约、哪个版本,chainId 说它声称是给哪条链用的,verifyingContract 说最后由谁来验这个签名。另一层是主类型,也就是这条消息结构自己的名字,Permit 这个词出现的位置就在这一层。

两层的读法我给个个人取舍:我自己习惯先看主类型再看域。主类型能在一两秒里告诉你「这到底是不是一张授权凭证」,而域那一层要发挥作用,前提是你手头有东西可以对照——你得知道自己在用哪条链、在跟哪个合约打交道,否则那两个值摆在眼前也只是没有参照物的字符串。反过来的顺序当然也行,别只看其中一层就下结论。

还有一处出处要交代清楚:EIP-712 在讲合规性的时候说,这套编码符合 ERC-191,版本字节固定为 0x01,版本相关数据是那 32 字节的域分隔值,待签数据是那 32 字节的消息结构哈希。这段话本站是从 EIP-712 页面上读到的,EIP-191 的原文本文没有打开,别把它当成 191 那边的完整说法。

Permit 长什么样:五个字段逐个对

ERC-2612 做的事,用它摘要里的原话说,是给 EIP-20 标准加一个 permit 函数,让用户可以用一条签名消息来修改额度表,而不必通过发起交易的那个地址去改。动机段给了理由:在没有 permit 的年代,用户得先授权再调合约,需要发两笔交易,并且必须自己持有 ETH 来付 gas。被你签的那条消息,主类型叫 Permit,字段逐字是这样的:

Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)

这五项在弹窗里可以一个一个对过去。owner 是额度被修改的那个地址,正常情况下就是你自己;spender 是额度给谁,这一项最该让你把手指从确认键上挪开几秒;value 是给多少,注意它是一个数额而不是一个开关,数字大到离谱的时候,你交出去的就接近一张没有上限的票;nonce 是这张凭证对应的序号;deadline 是过期时间,过了这个点它就作废。

规范列了四个条件,全部成立这条 permit 才会生效,否则合约会直接回滚:当前区块时间小于等于 deadlineowner 不是零地址;状态更新之前的 nonces[owner] 正好等于消息里的 nonce;以及签名是 owner 对这条消息的有效签名。四条都满足时,合约会把 allowance[owner][spender] 设成 value,把 nonces[owner] 加一,并发出一个对应的授权事件。说白了,一个 Permit 签名就是一张代币额度授权凭证,它改动的和你在链上点一次授权改动的是同一张额度表,读它的标准也就和你检查现有授权的标准一样。手边可以配着本站的授权风险自查清单过一遍。

签完之后会发生什么

ERC-2612 的安全考量里有两条讲的是同一件事的两面。一面是:签名方心里可能有一个特定的提交者,但任何其他人都可以抢先一步,赶在预期的那一方之前去调用 permit;原文还补了一句,对签名者来说最终结果是一样的。另一面是:已签的 Permit 消息是可以被压住的,收到签名的那一方完全可以选择不提交,把「要不要交上去」这个选择权攥在自己手里;紧接着规范指出,deadline 这个参数是针对这件事的一个缓解手段。

合起来,这一节标题的答案就出来了:签完那一刻,链上可能什么都没有发生,你去区块浏览器上查,一片安静。但这只说明这张票还在别人手上,而且在 deadline 到期之前的任何一个时刻、由任何一个人,都可以拿去兑现。

别搞反的一条「查不到记录」和「没生效」是两件事。前者是现在的状态,后者是对未来的结论,签名请求这件事上,你没有资格从前者推出后者。

那已经签出去的还能不能作废?ERC-2612 页面上只给了一条:签名方如果手里有 ETH,可以自己提交一次 permit,让此前签出去的失效——原理是生效时 nonces[owner] 会加一,旧签名里那个 nonce 就对不上生效条件的第三条了。要强调的是,这是该页给出的唯一一条;本文没有核过任何第三方撤销工具,所以不给工具的操作步骤,也不敢保证这一招一定来得及,因为在 deadline 之内,对方随时可能先你一步。这也是我建议你多看 deadline 两眼的原因——它是整张凭证上唯一一个直接告诉你「这东西还能用多久」的字段,我自己的习惯是顺手把那个时间戳换算成本地时间看一眼。

防重放不是签名机制自带的

EIP-712 摘要的最后一句很短,短到容易被跳过:它不包含重放保护。那靠什么防?靠被签的那个结构自己带的字段,加上域里那几项——nonce 让同一张票只能被兑一次,因为它一旦生效序号就往前推了;deadline 给这张票加了一个到期时间;域里的 chainIdverifyingContract 则把它钉在某一条链、某一个合约上。

ERC-2612 的安全考量里还有一条能佐证这层关系:如果合约的域分隔值把 chainId 在部署时就定死,而不是每次签名重新构造,那么将来一旦发生链分裂,就存在跨链重放的风险。这本来是合约实现者要操心的事,却正好解释了域里为什么非得有 chainId 这一项。读者这边能做的判断有限:结构里看得见 noncedeadline,至少说明这条消息带了这两层;取值是不是合理,只能你自己结合当下在做的事去衡量。

看不懂、拿不准要不要签的时候

最实用的一条毫无技术含量:看不懂就先不签。签名请求在绝大多数正经流程里都可以拒绝之后重新发起,多花两分钟核对不会让什么东西永久失效;如果某个流程逼着你立刻签、或者给出的期限短得反常,那本身就值得停下来问一句。

要在几十秒里把一个请求读开,我的顺序大致是这样:先确认它属于哪一类——看得见字段名的是结构化数据,只有一段人话的是纯文本消息,要你出 gas 的是交易;确认是结构化数据之后去找主类型那个名字,看到 Permit 就知道下面那五个字段该怎么一个个对;字段全都不见、只剩哈希的,当成内容不明处理,别自己脑补。还有一个比对字段更重要的动作:把「我以为自己在做什么」和「这条消息声称在做什么」摆在一起对一遍。你点的是登录,结构里却躺着一份额度授权,这个落差不需要任何技术知识也能看出来。想练练手感,本站的防钓鱼自测里有几道情景题。

最后区分一下适用范围。这篇讲的自始至终是别人递到你面前的请求;你自己发起一笔转账、在设备上走离线签名的那套流程跟这里说的是两码事,本站冷钱包怎么转账写了那一条链路。整套自托管的防护怎么咬合在一起,可以回看自托管完全指南

常见疑问

签名不花 gas,是不是就不会有损失?

花不花 gas 只说明这一步有没有发交易,和后果大小没有关系。按 ERC-2612 的设计,一个 Permit 签名生效之后会把 allowance[owner][spender] 设成消息里的 value 并把 nonces[owner] 加一——改的是额度表,和你在链上点一次授权改的是同一张表。不花 gas 恰恰是它被设计出来的卖点,规范的动机段里写得很清楚:没有 permit 的时候用户要发两笔交易,而且得持有 ETH 来付 gas。

我签了一个 Permit,区块浏览器上查不到记录,是不是没生效?

查不到只说明还没有人把它提交上链,不说明它作废了。ERC-2612 的安全考量一节写明,拿到签名的一方可以选择收下之后先不提交、把提交的权利攥在手里;同时任何第三方都可以抢在原本预期的提交者之前调用 permit。在 deadline 到期之前,这张签名一直是可以被兑现的。

已经签出去的 Permit 还能撤销吗?

ERC-2612 页面上只给了一条办法:签名方如果手里有 ETH,可以自己提交一次 permit,从而让此前签出去的 permit 失效——原理是生效时 nonce 会加一,旧签名里的 nonce 就对不上了。本文没有核任何第三方撤销工具,所以不给工具的操作步骤,也不能告诉你这一条一定来得及:在 deadline 之内,别人随时可能先你一步提交。

钱包上只显示一串哈希(盲签)、看不到任何字段,能签吗?

那等于你不知道自己在签什么。EIP-712 的出发点就是解决这个问题,它的摘要原文说,当时被签的消息是一串不透明的十六进制字符串、几乎不给用户任何上下文,而这份提案给出的方案是把数据连同结构一起编码,以便在签名时展示给用户核对。看不到结构,要么这个请求走的不是这条路,要么你手上这台设备或这个钱包没有把它解析出来。各家钱包与硬件设备的解析能力差别很大,以你手上那台实际显示的为准。

弹窗里的 deadline 设得特别久,有问题吗?

deadline 是这张凭证的有效期,也是 ERC-2612 明确点名的缓解手段——它在安全考量里被写成对签名被攥着不交这件事的一个 mitigation。期限越长,这张票能被兑现的窗口就越长。ERC-2612 页面上没有规定该设多久,所以没有一个标准答案,但把它换算成你看得懂的日期看一眼,总比只盯着一个时间戳强。

何沂 · 守钥编辑
写新手入门与防骗,自己也清理过不少忘了关的旧授权
"何沂"是笔名,我不假装自己是合约审计专家。这篇能写死的部分全部来自 EIP-712 与 ERC-2612 的规范原文,钱包和硬件设备那一侧的显示行为本文没有核,所以一句都没有替厂商说。链上操作不可逆,本文是安全教育、不构成投资建议,最后每一次签名都该你自己看明白再按下去。

本文核对日期 2026-09-19 · 规范内容以 eips.ethereum.org 上 EIP-712 与 ERC-2612 的当期页面为准 · 各家钱包与硬件设备的显示行为本文未作核验 · 发现错漏欢迎通过联系页指正,更正会记录在更正页

类目:授权、钓鱼与被盗急救