EIP191和EIP712的区别

以太坊上面签名随处可见,在智能合约中,也需要处理签名数据。

比如在Uniswap V2的代码中,可以传入一段签名数据,代码会判断数据的签名者是否是owner本身。

人们喜欢规范,于是就给智能合约中的签名数据制定了一个数据格式:EIP191。

结论

  • EIP191编码是为了定义智能合约中签名数据的格式
  • EIP712是EIP191的一种
  • EIP712解决了重放攻击和结构体编码规范的问题

EIP191

EIP191的数据格式为:

0x19 <1 byte version> <version specific data> <data to sign>.
  • 0x19是前缀
  • 1个1字节的版本号
  • 版本号特有的数据
  • 签名数据本身

有了这个数据格式,人们就会先把数据按照EIP191的格式组装起来,然后进行签名。签名的数据在智能合约中也按照EIP191的格式进行验证。

目前一共有三个版本号:

Version byteEIPDescription
0x00191Data with intended validator
0x01712Structured data
0x45191personal_sign messages

version 0x00

这种版本的数据格式为:

0x19 <0x00> <intended validator address> <data to sign>

其中往往是合约地址。这样做的好处是签名仅对某合约有效,一定程度避免重放攻击。

比如你有一段数据“abc“需要签名,在合约地址0xffff中使用,则常见的步骤为:

  1. 拼接EIP191数据格式: data=0x19 0x00 0xffff abc
  2. 把拼接好的数据做哈希运算:hash = keccak256(data)
  3. 签名数据
  4. 把数据发送给合约,合约调用ecrecover计算出签名人地址
  5. 验证签名人是否合法

version 0x45

这种版本的数据格式为:

0x19 <0x45 (E)> <thereum Signed Message:\n" + len(message)> <data to sign>

注意,0x45对应的ascii编码就是字母E。这个版本其实是把personal_sign方案纳入到了EIP191中。

version 0x01

这个版本的就是EIP712。也就是EIP712其实也是EIP191的一种。

几个问题

  1. 为什么采用0x19作为前缀

以太坊中大量使用了RLP格式编码,为了和RLP编码区分,EIP191采用了0x19作为EIP191数据的前缀。

因为RLP编码的数据,如果是0x19作为前缀,其仅代表着一个单字节。不可能像EIP191一样,0x19后面跟着一串数据。因此EIP191数据和RLP编码的数据就能区别开来。

  1. EIP191中0x00的版本与0x45有什么区别

这是一个历史原因。一开始并没有EIP191格式,人们常用的是最初由 Geth 实现(https://github.com/ethereum/go-ethereum/pull/2940)的 personal_sign方案,数据格式为:

"\x19Ethereum Signed Message:\n" + length(message) + message

而人们往往会对message做哈希运算,因此更常见的格式为:

"\x19Ethereum Signed Message:\n32" + Keccak256(message)

在这基础之上拓展了EIP191,EIP191是以0x19为前缀,再加一个版本号,personal_sign方案并没有版本号,因此就把第一个字母“E”,作为版本号,曲线救国。

EIP712

EIP712是EIP191的一种。

EIP191有几个问题:

  1. 没有明确防止重访攻击的规定
  2. message如果是一个结构体,则没有对应的编码规范,开发者可以按照自己的方式进行编码,造成一些外部组件,比如钱包,无法解析编码

EIP712就是为了解决以上两个问题:

  1. 通过DOMAIN_SEPARATOR设定,防止重放攻击
  2. 规范对结构体编码的方式

首先直观的对比下差别:

左边是EIP91编码,可以看到message是一堆不可读的字符串,右边是EIP712编码,可以知道结构体的具体数据。

我们来具体看看EIP712如果做到的。

1. 通过DOMAIN_SEPARATOR设定,防止重放攻击

还记得EIP712是EIP191的一部分吗,我们看一下EIP191的数据格式:

0x19 <1 byte version> <version specific data> <data to sign>.

对EIP712而言,1 byte version对应的版本号就是0x01。

version specific data中,则存放着DOMAIN_SEPARATOR的哈希,DOMAIN_SEPARATOR是一个结构体,如下:

struct EIP712Domain{
    string name, //用户可读的域名,如DAPP的名字
    string version, // 目前签名的域的版本号
    uint256 chainId, // EIP-155中定义的chain ID, 如以太坊主网为1
    address verifyingContract, // 用于验证签名的合约地址
    bytes32 salt // 随机数,这个往往被省略
}

有这个数据,即包括chainID,又包括合约地址,还包括app名字,版本号等数据,不可能被重放攻击了吧。

现在假设我们有一段数据“abc“需要通过EIP712签名,则步骤为:

  1. 准备前缀。prefix = 0x19 0x01
  2. 计算DOMAIN_SEPARATOR的哈希
DOMAIN_SEPARATOR_HASH = keccak256(
      abi.encode(
          // encodeType
          keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
          // encodeData
          keccak256(bytes(name)),
          keccak256(bytes('1')),
          chainId,
          address(this)
      )
 );

3. 拼在一起:

0x19 0x01 DOMAIN_SEPARATOR_HASH "abc"。

2. 规范对结构体编码的方式

上面的例子中,讲了DOMAIN_SEPARATOR的作用,然后用了一个非结构体“abc”举例,现在我们用来看看结构体怎么编码。

     // Mail 是待签名的结构体
    struct Mail {
        address from;
        address to;
        string contents;
    }
    
    //对结构体编码
    messageHash = keccak256(
            abi.encode(
                keccak256("Mail(address from,address to,string contents)"
                mail.from,
                mail.to,
                keccak256(bytes(mail.contents))
            )
        );

可以看到messageHash中,把结构体名称,属性名称都编码进去了,因此钱包等第三方能够知道编码的结构体数据结构。解决了结构体编码的规范

再集合前面DOMAIN_SEPARATOR的例子,最终的EIP712编码就为:

0x19 0x01 DOMAIN_SEPARATOR_HASH messageHash

再把EIP712编码的数据求一个哈希,签名,就可以发送给智能合约了验证了。

Ref



《 “EIP191和EIP712的区别” 》 有 4 条评论

  1. where can i get cytotec without a prescription com 20 E2 AD 90 20Viagra 20100mg 20Vs 2050mg 20 20Fabriquer 20Du 20Viagra 20Maison fabriquer du viagra maison DHAKA, Oct 24 Reuters Clothing chain Primark laid outplans on Thursday to pay more compensation for the Rana Plazafactory disaster in Bangladesh as victims and their familiesdemanded other western brands follow suit

  2. It is also clear from Dutch and foreign patient surveys that this form of CBT does not help the majority of patients and leads to deterioration in a considerable number of patients where to get generic cytotec prices

  3. Dongcheng Hanguang how to tell the difference between hemp and marijuanas said without hesitation can you buy priligy Zhang Quhua is erectile dysfunction in porn a young man who became famous at a young age, and finally became the champion in high school

  4. The active ingredient erlotinib belongs to a class of medications called tyrosine kinase inhibitors priligy 60 mg The absence of TILs in the microenvironment could point to defects in the adaptive immune cycle

回复 agodelo 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

About Me

一位程序员,会弹吉他,喜欢读诗。
有一颗感恩的心,一位美丽的妻子,两个可爱的女儿
mail: geraldlee0825@gmail.com
github: https://github.com/lisuxiaoqi
medium: https://medium.com/@geraldlee0825