Bupt3分享22—拆解以太坊密钥系统

在转向权益证明之前,以太坊用户只有一套基于椭圆曲线的公私钥来访问他们的资金。随着权益证明的引入,成为 solo staker 的用户还需要验证者密钥(validator key)和提款密钥(withdrawal key)。本课题旨在研究以太坊引入新密钥体系的原因,以及验证者密钥和提款密钥的工作原理。

一、传统公私钥对

以太坊使用公私钥加密技术来保护用户资产的安全,采用了椭圆曲线密码学 (Elliptic Curve Cryptography, ECC)。其中公钥作为公开可见且唯一的标识符,是以太坊地址的基础;私钥用于“签署”交易和数据,作为帐户所有者才有权访问,以便密码学判定所有者是否批准某些行为。

在以太坊1.0,用户访问他们的资金只需要一个私钥,而在以太坊从工作量证明转换到权益证明的时候,一种新类型的密钥被加入到以太坊。原来的密钥仍然像之前那样工作—基于椭圆曲线的密钥确保帐户安全没有变化,通过质押以太币和运行验证者来参与权益证明时,用户需要一种新类型的密钥用于识别每个验证者的身份,从而我们将验证者行为 (无论好坏) 追溯到验证者本身。同时,由于 PoS 后信息需要在大量验证者之间传递,这些信息需要一种密码学方法来方便汇总,以减少网络达成共识所需的沟通数量。这种新型密钥使用 Boneh-Lyn-Shacham (BLS) 签名方案。 BLS 能够对签名进行高效聚合,同时允许对聚合的单个验证者密钥进行逆向工程,它对于管理验证者之间的行动非常理想。

在eth2中,每个验证者的身份标识便是他们的公钥。具体来说,每个验证者会有两组密钥:签名密钥和提款密钥。

二、VALIDATOR KEY

签名密钥是验证者需要用于签名证明 (attestation) 和提议区块的密钥。由于一个验证者在每个 epoch 内至少需要对一条消息进行签名,客户端软件必须对签名密钥进行托管。

验证者的签名密钥由两个元素组成:验证者私钥 和 验证者公钥。验证者私钥的目的是签名链上操作,如区块提议和认证。 因此,这些密钥必须存放在热钱包中,因此密钥完全有可能受到威胁;这种灵活性的优势是可以快速地把验证者的签名密钥从一台设备转移到另一台,然而,如果密钥丢失或者被盗,盗窃者可以通过这些方式恶意地行动:

  • 通过以下方式罚没验证者:
    • 作为一个提议者,在同一个 slot 签名两个不同的信标区块
    • 作为一个证明人,签名“包裹”另一份认证的认证
    • 作为一个证明人,签名两个具有相同目标的不同证明
  • 促使自愿退出,从而停止验证者质押,并授权提款密钥拥有者获取以太币余额。

为了减轻相应影响,验证者的提款操作需要通过另一套密钥来实现。

三、WITHDRAW KEY

每个验证者都有一个被称为「提款凭证」的属性,要么是 0x00 开头的 32 字节字段,表示 BLS 提款凭证,要么是 0x01开头,表示指向执行地址的凭证。

具有 0x00 BLS 密钥的验证者必须更新这些凭证,使其指向执行地址,以便激活从质押进行超额余额支付或全额提款。这可以通过在初始密钥生成期间在存款数据中提供执行地址,或者通过稍后使用提款密钥签署并广播 BLSToExecutionChange 信息来实现。

和验证者密钥一样,提款密钥也由两个部分组成:提款私钥&提款公钥。在将提款凭证更新为 0x01 类型之前丢失此密钥,意味着失去对验证者余额的访问权限。验证者仍然可以对认证和区块进行签名,因为这些操作只需要验证者的私钥,但如果提款密钥丢失,那就几乎没有任何奖励。

把验证者密钥和以太坊帐户密钥分开,可以让一个用户运行多个验证者。

四、密钥太多怎么办?

如果每质押 32 ETH,质押者都需要保存并且使用两种不相关的密钥来进行存款,那么局面很快就会失控。幸运的是,对此我们有一个解决方案:为密钥设置一个共用密钥,这样一来仅需存储一个密钥就可以访问多个密钥。

在 eth2 中,这个解决方案通过 EIP 23332334 实现:这组标准描述了提款密钥和签名密钥之间的关系,以及如何从单个助记符中导出它们。

从助记词派生密钥

在使用硬件钱包时,你可能会碰到格式为 m/44’/60’/0’/0/0 的“路径”。这些路径描述了密钥之间的关系。根据 EIP 2333 ,其关系采用树结构的形式,其中密钥由熵源 (树的seed) 和树路径确定。

我们使用 seed 来计算树根,然后在基于树根层层构建,该密钥树完全根据其后分支之间的关系和树根来进行定义。实际上,这使得我们可以从树的根部开始,并在每个分支上计算中间键,然后抵达相关叶子节点,从而在树中找到需要的任何键。奇妙之处在于,我们可以从单个熵源 (比如一个助记符) 开始,然后基于此衍生出实际上无限数量的密钥。此外,通过仅存储该助记符,你可以备份作为验证者所使用的每个密钥。

Eth2 就运用了这种理念,允许通过单个助记符来生成验证者需要的任意数量的密钥。举个例子,如果你想运行 3 个验证者节点,那么你可以借助单套助记词来生成位于m/0, m/1, m/2 的 3 个提款密钥。每个分支都由 / 隔开,因此 m/2 表示从主密钥开始并跟随第 2 条分支。

EIP 2334 中,验证者的签名密钥是提款密钥的第 0 个子分支。也就是说,在实际情况中,如果知道了用于提款密钥,那么你可以计算出相应的签名密钥。继续上方的例子,我们可以在 m/0/0, m/1/0, m/2/0 找到相应的三个签名密钥。

为了阐明概念,上面的例子尽可能简化了,但实际上涉及的路径要长一些 (EIP 2334 要求分别使用 m/12381/3600/i/0m/12381/3600/i/0/0 的路径来获得提款密钥和签名密钥)。但其中的逻辑和上面的例子相同。总而言之,需要记住的要点就是:如果你知道助记符,那你就可以计算出提款密钥,继而通过提款密钥得到你的签名密钥。

写在最后

以太坊 1.0 和 2.0 的密钥是基于相同的思路并使用椭圆曲线密码学创造出来的。但是,以太坊 2.0 的功能性有所增强,在创造密钥时需要不同的参数,并使用 BLS (Boneh-Lynn-Shacham) 签名方案,目的是处理网络中更多的信息,以及区分投票地址是否正确履行职责。

参考

EF Blog: Validated, staking on eth2: #4 - Keys 🔑 | Ethereum Foundation Blog

Ethereum Official: Keys in proof-of-stake Ethereum | ethereum.org

Ethereum 2.0 Keys: Ethereum 2.0 Keys | beaconcha.in Knowledge Base