本文作者:影无双[1]
我花了太多时间来弄清楚如何生成并验证类型结构化数据签名,所以整理这篇文章希望可以帮你节省点时间。
我正在进行的项目[2],需要用户用钱包签署一些数据。通常,我只会用个人签名[3],但是在一些情况下,数据有特定的格式,我想让钱包签名提示看起来更好一些。
以太坊的签名
用以太坊钱包对数据签名时,有多种方式可以选择。你可以用“普通的”,可以签名任何字符串(在签名交易时用的);你可以用个人签名,这会为签名信息添加一个前缀;或者你可以用类型结构化数据签名,它允许为用户需要签名的信息定义格式(并且签名提示显示更好)。
输入数据
在这个项目中,我决定使用类型结构化数据签名(EIP-712 签名)。首先,定义types
(消息要用的结构)和domain
(关于 app 的信息)。
// Let's assume we're signing an email message
const message = {
from: {
name: 'Miguel Piedrafita',
wallet: '0xE340b00B6B622C136fFA5CFf130eC8edCdDCb39D'
},
to: {
name: 'Alex Masmej',
wallet: '0xD3e9D60e4E4De615124D5239219F32946d10151D'
},
contents: 'We need more NFTs.'
};
// Our domain will include details about our app
const domain = {
name: 'Ether Mail',
version: '1',
};
// Here we define the different types our message uses
const types = {
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallet', type: 'address' }
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person' },
{ name: 'contents', type: 'string' }
]
};
有了domain
和 types
,我们就可以用ethers.js
库来获取签名。
import { ethers } from 'ethers'
const web3 = new ethers.providers.Web3Provider(provider)
const signature = await web3.getSigner._signTypedData(
domain, types, message,
)
验证
现在我们只需要一种验证签名的方法。为此,我们需要前面生成的签名和签名的钱包地址,还有上一步中的domain
和 types
。
import { verifyTypedData } from 'ethers/lib/utils'
export const verifySignature = (signature, message, address): boolean => {
return verifyTypedData(
domain, types, message, signature,
).toLowerCase() === address.toLowerCase()
}
原文链接:https://m1guelpf.blog/lgIDdfbeDSElr0g7kaP0TZLkkjAqkQGPriauuYSrLlI
参考资料
[1]
影无双: https://learnblockchain.cn/people/58
[2]
项目: https://sonarwave.xyz
[3]
个人签名: https://learnblockchain.cn/article/3744