本章系统介绍了结构化签名标准 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'...
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!