跳到正文

EIP-712 类型化签名:域、摘要与安全验证

EIP-712 让以太坊结构化消息具备确定性并可供展示,但安全签名仍需核对确切的域、类型、值、Nonce、截止时间、执行方式和签名者策略。

更新于

仅供教育参考,不构成投资建议;投资可能产生损失。

直接答案

EIP-712 规定了以太坊应用如何描述、哈希并请求对类型化结构数据签名。请求包含 typesprimaryTypedomainmessage;其摘要为 keccak256("\x19\x01" || domainSeparator || hashStruct(message))。这样可确保编码具有确定性,也让具备相应能力的钱包能比不透明哈希更清楚地展示字段。

不会自动保证消息真实、无害、可撤销或不可重放。应用必须把权限绑定到正确的链和验证者,明确每个字段的含义,执行 Nonce 与时间限制,验证正确的签名者,并约束执行行为。有效签名只证明某个验证规则认可对特定摘要的签署;它不能证明签名者身份、知情意图,也不能证明网站或合约安全。

EIP-712 类型化签名
0 / 5
0 项已核查; 5 项仍未解决

完成核查不代表资产、交易或系统已经安全。

工作原理

1. 确认操作和验证路径

判断请求授权的是登录、订单、投票、代币额度、转账、中继调用还是其他操作。找到重建摘要并消费签名的代码。对于外部拥有账户,验证通常从 ECDSA 签名恢复地址;对于合约账户,应用可能需要调用 ERC-1271 isValidSignature(hash, signature),并检查其成功值 0x1626ba7e

2. 锁定域

检查确切的 EIP712Domain 类型和值。标准字段为 nameversionchainIdverifyingContractsalt,但只有实际包含的字段才参与哈希。独立确认当前链、已部署代码和预期验证者;熟悉的名称、代币符号、代理标签或校验和地址并不足够。ERC-5267 eip712Domain() 可以公开合约的域,但支持该接口并非强制,代理或升级行为仍需审查。

3. 重建类型图

primaryType 开始,保留成员顺序,并递归收集引用的结构体。encodeType 会按类型名称排序后附加被引用结构体的定义。EIP-712 支持定宽整数、addressboolbytes1bytes32、动态 bytesstring、数组和结构体;标准未定义 uintint 等别名、定点类型及循环值。

4. 解码每个值和单位

将每个消息值与其声明类型和应用含义对应起来。核对完整地址、原始整数单位、正负号、数组顺序、接收者、Spender、资产、金额、费用、限额、目标、Calldata 哈希及人类可读字符串。动态 bytesstringencodeData 中以其内容的 Keccak-256 哈希表示;数组对连接后的元素编码取哈希,嵌套结构体则使用各自的 hashStruct

5. 独立重算摘要

计算 typeHash = keccak256(encodeType(primaryType)),再计算 hashStruct(message) = keccak256(typeHash || encodeData(message))。以同样方式计算域分隔符,再与 ERC-191 版本字节 0x19 0x01 组合。比较前端、签名库、验证合约和独立实现得出的摘要;JSON 外观一致并不能证明类型化编码相同。

6. 审查重放、时间和执行控制

EIP-712 本身不包含重放保护。确认验证者会检查预期签名者、消费或作废正确的 Nonce、执行 deadline 或有效期限制、绑定全部安全关键执行参数,并在中继者或抢跑者先提交时仍产生相同的预期结果。域分隔只能防止实际编码域之间的冲突;缺失或错误的域字段可能留下跨合约或跨链复用路径。

7. 最小化签名并核对结果

拒绝隐藏字段、无法解释的类型、无限额度、遥远截止时间、未知合约、不匹配的链 ID、盲签屏幕或不完整的执行上下文。保留确切的类型化数据 JSON 和摘要,尽可能使用用途受限的账户,并检查已提交交易、收据、事件、余额、额度、Nonce、订单状态和最终性。断开网站连接不会撤销仍可用的签名或已经建立的权限。

计算示例

示例 1:类型与摘要构造

对于 Order(address maker,address token,uint256 amount,uint256 nonce,uint256 deadline)typeHash 是该完整字符串的 Keccak-256 哈希,字段顺序也必须完全一致。消息哈希为 keccak256(typeHash || maker || token || amount || nonce || deadline),每个编码成员占 32 字节。最终摘要加入 0x1901、域分隔符和该消息哈希;把 amount250000000 改为 250000001 就会改变摘要,使旧签名失效。

示例 2:单位与截止时间

六位小数代币的 250 USDC 应编码为原始值 250000000,而不是 250。若当前时间戳为 1727000000,截止时间为 1727000900,签名窗口就是 900 seconds = 15 minutes。钱包的小数显示和本地时钟仅供辅助;验证者使用原始整数及其选定的链上时间规则。

示例 3:重放控制

一笔订单携带 Nonce 41,最大成交量为 5 ETH。验证者将 Nonce 41 标记为已消费后,即使签名本身仍然有效,第二次提交也必须失败。如果合约既不消费 Nonce,也不让执行具备幂等性,同一签名便可再授权一笔 5 ETH;域分隔符本身无法阻止这种重放。

示例 4:合约钱包有效性

一个 2-of-3 合约钱包在配置签名者 A、B、C 时批准某摘要。A 和 B 的签名目前可能让 ERC-1271 返回 0x1626ba7e。若模块升级后用 D 替换 B,相同的签名字节可能失效,因为 ERC-1271 有效性可以取决于当前合约状态、策略、时间和外部调用;仅靠地址恢复无法判断合约账户的签名有效性。

风险

  • chainId 错误或缺失
  • verifyingContract 是仿冒地址或并非预期合约
  • 域的 nameversion 具有误导性
  • 代理实现或域在升级后发生变化
  • primaryType 错误,或使用标签相似的影子类型
  • 成员顺序、依赖顺序或编码器不一致
  • 地址被截断、替换或错误标注
  • 代币小数位或有符号与无符号整数错误
  • 隐藏的数组项、嵌套结构体或任意 bytes 载荷
  • 无限金额、过宽范围或由攻击者控制的接收者
  • Nonce 缺失、过期、共享或消费方式错误
  • 截止时间缺失、过远、溢出或解释含糊
  • 跨链、跨合约、跨账户或跨操作重放
  • 中继者扣留、审查、抢跑或重定向执行
  • 签名可塑性或过于宽松的 ECDSA 恢复
  • ERC-1271 签名者、模块、阈值、状态或代码变化
  • 钱包渲染、盲签或不支持类型导致的失败
  • 前端 JSON 与验证者使用的摘要不一致
  • 撤销或取消在交易排序竞争中失败
  • 将签名提示的结果误认为收据、状态变化或最终性

常见误区

误区 1:EIP-712 签名就是交易

它们是链下签署的消息。中继者或其他参与者可以随后把它们提交给合约,产生的交易可以消耗 Gas 并改变状态,却不必由签名者发送。

误区 2:结构化显示就代表请求安全

类型化字段提高了可检查性,但恶意模式、数值、合约、标签、隐藏嵌套和不完整的钱包渲染仍可能误导签名者。

误区 3:域分隔符能阻止所有重放

它只隔离已编码的域。同域重放仍需要 Nonce、截止时间、取消、成交量记账或幂等性;未包含的域字段不会形成任何边界。

误区 4:恢复出预期地址就证明获得授权

地址恢复只证明某 EOA 对摘要做了签名,不能验证应用语义;合约账户必须执行 ERC-1271 策略,而不是普通地址恢复。

误区 5:关闭页面或断开钱包连接会取消签名

复制出的签名会一直可用,直到验证者的 Nonce、截止时间、取消状态或策略使其失效。应确认相关链上状态,而不是依赖会话状态。

相关主题

来源

导航

搜索知识库...