Skip to main content

为什么需要 signTypedData

signTypedData 是以太坊(Ethereum)中的一种签名方法,主要用于签署结构化数据。它的引入旨在提高安全性和用户体验,与传统的消息签名方法(如 signMessage)相比有几个显著的优势。

为什么需要 signTypedData

  1. 自定义消息结构

    • signTypedData 允许开发者定义复杂的数据结构,并对这些结构进行签名。这比简单的字符串消息更灵活,可以用于各种应用场景,如智能合约交互、去中心化金融(DeFi)协议等。
  2. 防止重放攻击

    • 传统的消息签名方法(如 signMessage)容易受到重放攻击(Replay Attack)。重放攻击是指攻击者可以捕获并重放合法用户的签名消息,从而重复执行某些操作。signTypedData 通过包含域(domain)信息(如链 ID、合约地址等)来防止这种攻击。
  3. 更好的用户体验

    • signTypedData 提供了更丰富的上下文信息,使得用户在签名时可以清楚地看到他们正在签署的具体内容。这有助于减少用户错误签名的风险,提高了整体的安全性和用户体验。
  4. 标准化

    • signTypedData 是基于 EIP-712(Ethereum Improvement Proposal 712) 标准的,这个标准定义了结构化数据的签名格式和方法。使用标准化的方法可以确保不同的应用和钱包之间的兼容性。

示例

以下是一个简单的 signTypedData 示例:

const typedData = {
types: {
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' },
],
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallet', type: 'address' },
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person' },
{ name: 'contents', type: 'string' },
],
},
primaryType: 'Mail',
domain: {
name: 'Ether Mail',
version: '1',
chainId: 1,
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
},
message: {
from: {
name: 'Alice',
wallet: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
},
to: {
name: 'Bob',
wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
},
contents: 'Hello, Bob!',
},
};

// 使用以太坊钱包进行签名(例如MetaMask)
ethereum
.request({
method: 'eth_signTypedData_v4',
params: [signerAddress, JSON.stringify(typedData)],
})
.then((signature) => {
console.log('签名:', signature);
})
.catch((error) => {
console.error('签名错误:', error);
});

在这个示例中,typedData 包含了域信息、主要类型(primaryType)和消息内容。通过这种方式,用户在签名时可以清楚地看到他们正在签署的具体数据,减少了误操作的风险。

总结

signTypedData 提供了一种更安全、更灵活的签名方式,特别适用于需要签署复杂数据结构的场景。它通过标准化和提供更丰富的上下文信息,显著提高了用户体验和安全性。