本章系统介绍了结构化签名标准 EIP-712,从设计动机、安全特性到工程实现进行了全面剖析。相较于传统的 personal_sign(EIP-191)文本签名,EIP-712 支持结构化 TypedData 数据类型,具备更高的安全性、可读性与合约兼容性。我们详细解析了 EIP-712 签名格式中的
📚 作者:Henry 🧱 系列:《Web2 到 Web3:登录与身份验证机制全面进化》 · 第 3 篇 👨💻 受众:Web2 & Web3 开发者 / 区块链学习者 👉 系列持续更新中,建议收藏专栏或关注作者
EIP-191(即 personal_sign)的核心问题:
EIP-712 将签名对象结构化为“带类型的 JSON Schema”,解决以上问题。
一个结构化签名由三个部分组成:
{
  domain: DomainData,
  types: Record<string, TypeField[]>,
  message: Record<string, any>,
}
const domain = {
  name: 'MyDApp',
  version: '1',
  chainId: 1,
  verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
};
const types = {
  Login: [
    { name: 'wallet', type: 'address' },
    { name: 'nonce', type: 'string' },
    { name: 'issuedAt', type: 'string' },
  ],
};
const message = {
  wallet: '0xAbC123...',
  nonce: 'f92a1e',
  issuedAt: new Date().toISOString(),
};
| 字段 | 含义 | 
|---|---|
domain | 
用于防止跨 DApp 签名复用,绑定站点、合约等上下文 | 
types | 
所有结构体定义,包括主要的 message 类型及依赖 | 
primaryType | 
默认为 message 的类型,决定签名根结构 | 
message | 
需要用户签名的数据实例 | 
| 特性 | EIP-191(personal_sign) | 
EIP-712(signTypedData) | 
|---|---|---|
| 数据格式 | 普通字符串 | 结构化 JSON + 类型信息 | 
| 安全性 | ⚠️ 用户不可读、易钓鱼 | ✅ 明确字段、上下文可读 | 
| 与合约兼容 | ❌ 无法在合约中还原数据 | ✅ 可用于 MetaTx、Permit | 
| 校验粒度 | 仅地址校验 | 可结合合约函数参数校验 | 
| 实用场景 | 登录签名、轻量身份认证 | DeFi 授权、NFT 元交易、Login v2 | 
以如下结构作为签名类型(Login 示例):
type LoginMessage = {
  wallet: string;
  nonce: string;
  issuedAt: string;
};
const domain = {
  name: 'DApp Login',
  version: '1'...                                如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!