为了方便理解以太坊数据签署发展历史 ,第一篇文章我们先从metamask工具签署数据开始讲起,在第二篇文章我将讲一些实际使用案例,以及代码实现,当然他还有更多的使用场景,大家可以去想象。
由于 MetaMask 为每个用户提供加密密钥,因此网站可以将这些签名用于各种用途。以下是一些与特定用例相关的指南:
如果您想跳转到一些工作签名示例,可以访问此存储库 (打开新窗口).
如果你想阅读这些方法的 JavaScript 实现,它们都可以在 npm 包eth-sig-util 中找到 (打开新窗口).
请注意,MetaMask 支持使用 Trezor 和 Ledger 硬件钱包签署交易。这些硬件钱包目前仅支持使用该personal_sign
方法对数据进行签名。如果您在使用 Ledger 或 Trezor 时无法登录网站或 dapp,则该网站可能会要求您通过不受支持的方法签署数据,在这种情况下,我们建议您使用标准 MetaMask 帐户。
MetaMask 目前有六种签名方法,您可能想知道这些方法的历史。研究这些方法的历史可以为分散标准的出现提供一些指导教训。我们目前的五种方法是:
eth_sign
personal_sign
signTypedData
(目前与 相同signTypedData_v1
)signTypedData_v1
signTypedData_v3
signTypedData_v4
随着时间的推移,可能还会有更多。当 MetaMask 刚开始时,Provider API 并没有被设计为暴露给不受信任的网站,因此有些考虑没有像后来那样认真。
特别是,该方法eth_sign
是一种开放式签名方法,允许对任意散列进行签名,这意味着它可用于对交易或任何其他数据进行签名,使其具有危险的网络钓鱼风险。
出于这个原因,我们使这种方法向用户显示最可怕的消息,并且通常不鼓励在生产中使用这种方法。但是,一些应用程序(通常是团队内部的管理面板)出于易用性的考虑而使用此方法,因此我们继续支持它,以免破坏活动项目的工作流程。
最终,personal_sign
规范 (打开新窗口)被提议,它为数据添加了一个前缀,因此它不能模拟交易。我们还使此方法能够在 UTF-8 编码时显示人类可读的文本,使其成为站点登录的流行选择。
然而,文本前缀使得这些签名在链上验证的成本很高,因此在0xProtocol的帮助下 (打开新窗口)团队和SpankChain (打开新窗口), EIP-712 (打开新窗口)规范已写。
EIP-712 和这个去中心化标准生态系统的奇怪之处在于,该提案多次更改,但仍保留相同的 EIP。这意味着我们最初实现的signTypedData
是最早提出的版本,而其他小组以相同的方法名称实现了更高版本。
为避免客户端之间的兼容性问题,我们建议使用硬版本化的方法名称signTypedData_v1
和signTypedData_v3
. 缺失v2
代表了由 Cipher 浏览器实现的中间设计,因此如果有足够的开发人员需求,我们就有实现它的空间。
将来,让方法名称包含其确切提议的哈希值可能会有所帮助,因为在分散的生态系统中,给定名称应该映射到什么没有绝对的真实来源。相反,我们被迫发明新的合作模式,我们可以在其中推动和创新,同时避免通过改变我们的含义来避免创建脆弱的生态系统。
我希望这是对我们签名方法历史的有用介绍!
这个早期版本的规范缺乏一些后来的安全改进,通常应该忽略,而支持signTypedData_v3。
也称为signTypedData
,最初于 2017 年 10 月在此博客文章中首播 (打开新窗口),这种方法是原始的以状态通道为中心的签名方法。
该signTypedData
系列有几个主要的设计考虑:
如果链上可验证性成本对您来说是一个高优先级,您可能需要考虑它。
该方法signTypedData_v3
当前代表EIP-712 规范的最新版本 (打开新窗口),使其成为我们迄今为止签署成本低廉的链上数据的最安全方法。
这并不意味着它是完美的,我们确实已经有了一个v4
原型阶段(它支持递归结构和数组),但我们确实打算保护这个命名空间并保持它的兼容性。
我们在这里有一篇关于此方法的精彩介绍性博客文章 (打开新窗口).
希望很快我们也会有很好的例子来解析方法输入到结构中以进行链上验证(巨大的贡献机会!)
该方法signTypedData_v4
当前代表EIP-712 规范的最新版本 (打开新窗口),增加了对数组的支持,并对结构的编码方式进行了重大修复。
这并不意味着它是完美的,也不意味着我们最终不会有v5
.,但我们确实打算保护这个命名空间并保持它的兼容性。
我们在这里有一篇关于此方法的精彩介绍性博客文章 (打开新窗口).
希望很快我们也会有很好的例子来解析方法输入到结构中以进行链上验证(巨大的贡献机会!)
domain
:域或域签名很重要,因为它:
chainId
:chainId 告诉你你在哪个链上,这很重要,因为:
name
:这主要是出于 UX(用户体验)目的。
verifyingContract
: 这是额外的保证。即使两个开发人员最终创建了一个同名的应用程序,他们也永远不会拥有相同的合约地址。(您可以添加另一个字段salt
,但这完全是矫枉过正且不必要)
version
: 这告诉你当前版本的域对象。
message
: 对你想要的结构完全开放。每个字段都是可选的。
下面是使用 MetaMask 签署类型数据的示例。参考这里https://github.com/danfinlay/js-eth-personal-sign-examples
链接:Signing Data | MetaMask Docs