本文介绍了Chorus One团队开发的以太坊密钥生成工具Eth-staking-smith,该工具旨在解决大规模生成以太坊验证者密钥时面临的安全性、性能和依赖性问题。文章详细描述了该工具的架构、功能、用法以及安全性改进措施,并展示了如何使用该工具生成密钥、keystore和存款数据,以及如何将BLS提款地址转换为执行地址。
作者:Jennifer Parak,Maksym Kulish
2022 年加密社区最重要的事件之一是以太坊协议的 The Merge 升级,它将以太坊从 Proof-of-Work 传统链实现切换到 Proof-of-Stake 信标链。它已经证明,对于最古老和最大的去中心化系统来说,主要的创新是可能的,而不会对协议用户造成任何干扰。
在 Chorus One,自从信标链于 2020 年启动以来,我们一直致力于保护下一代以太坊的安全,并且今天我们在主网上运营着数千个验证器。我们的新产品 OPUS — 一个以太坊验证即服务 API — 旨在使任何组织和个人都能够在以太坊信标链上运行 staking 验证器客户端,采用非托管、无需许可的方式,我们要求客户指定他们自己的提款和费用接收地址,以便他们仍然拥有他们的 stake 资金和奖励。这篇文章重点介绍了我们的验证即服务 API 产品中验证器密钥配置和存储方法的技术实现,并展示了我们在此过程中遇到的一些挑战和创建的解决方案。
除了在信标链中保持不变的传统链钱包密钥之外,The Merge 还引入了两种参与保护以太坊链安全的新型密钥 [1]。这些密钥由签名(验证器)密钥对和提款密钥对组成。除了新的密钥功能之外,签名密钥还使用了一种新的密码签名方案,称为 BLS,代表 Boneh–Lynn–Shacham。这意味着较旧的密钥生成工具将无法用于创建签名密钥。BLS 签名,特别是那些在 BLS12–381 曲线上的签名,用于信标链块签名和 attestation。这使得聚合多个签名并在单个操作中验证它们成为可能,这是可扩展性的一个突出的改进 [2]。
像大多数其他 Proof-Of-Stake 区块链一样,下一代以太坊依赖于验证器的功能来确保交易流程的安全。 验证器是网络成员,他们锁定一部分以太坊币(最少 32 ETH),负责提议新的已签名交易块,并验证其他验证器的此类签名,这称为 attesting。 通常,每个以太坊验证器应该在每个以太坊 epoch(大约 6.4 分钟)内 attesting 一次签名; 并且对于每个 epoch 中的每个 slot,伪随机地选择一个验证器来生成一个交易块,供其他人 attesting。 验证器会因 block proposal 和 block attestation 而获得奖励。 签名块和验证其他人的签名的机制依赖于签名密钥对。 验证机制之所以有效,是因为签名密钥的每个公共部分(Public Signing Key)都发布在链上,因此使用签名密钥的私有部分(Private Signing Key)完成的每个签名都可以被每个其他验证器验证。 尽管拥有创建区块链内容的权力,但签名密钥不能用于转移任何资金,包括 staking 资金,它们只会监听并签署对等以太坊节点网络提供的交易内容。
提款密钥对既不用于块,也不用于 attestation,但它可以控制已 stake 的资金。在 Shanghai 分叉之后,提款将被激活,这将使资金能够转移到存款合约中指定的由所有者控制的提款地址。 通过 EIP-4895,提款将以推送方式启用 [3],这样先前在共识层上锁定以进行存款的资金将自动作为系统级操作推送到执行层。 这意味着用户无需为提款交易支付任何 gas。 对于在其存款合约中指定了 BLS 提款地址的用户,他们需要向信标链广播一个 BLS_TO_EXECUTION_CHANGE 消息,以将其提款地址更新为执行地址。
最后,当验证器成功提议一个块时,一个特殊的费用接收地址会收到来自该块的累积 gas 费用。由于费用接收者没有直接参与 staking,因此我们将在本文中主要省略它。
有关以太坊 staking 中涉及的不同类型密钥的更多信息,请参见以下资源:[4],[5]
作为 OPUS 验证即服务 API 的一部分,我们要求客户保留提款密钥的所有权,以便 Chorus One 永远无法控制或访问已 stake 的资金。但是,签名密钥是不同的:由于 Chorus One 是托管和维护以太坊验证器的责任方,因此验证即服务 API 的内部工作原理要求我们生成、加载和存储签名密钥。因此,一个强大的密钥管理解决方案是我们验证即服务 API 的重要组成部分。
在项目生命周期的早期,我们使用了以太坊基金会提供的 staking 存款命令行界面(CLI)( https://github.com/ethereum/staking-deposit-cli)。虽然 staking CLI 是一个很棒的单人/家庭 staker 工具,但我们意识到它不是为我们的用例设计的。首先,staking-deposit-cli 默认将新生成的 keystore 存储到文件系统中,从而构成密钥材料泄漏的潜在安全威胁。虽然可以使用特定于基础设施的解决方法(如 ramdisk)来减轻威胁,但此类解决方法会增加平台的复杂性和故障点。 staking-deposit-cli 的开源性质使我们能够 fork 源代码并对其进行修改以满足我们的需求,但是缺乏彻底的自动化测试套件意味着我们很难将我们的更改与上游更新同步。最后,我们所有的代码库都是 Rust,并且必须在基础设施中支持 Python CLI,包括及时修补所有 Python 依赖项以保持良好的安全记录,这给开发团队带来了额外的负担。最后,我们决定采用另一种生成密钥的方法,我们将在下一段中进行描述。
在生成大规模以太坊密钥时,由于使用 staking-cli 遇到了更多的困难,我们的以太坊团队决定在我们公司的工程 hackathon 期间解决这个问题,在那里我们构建了一个用 Rust 编写的以太坊密钥生成工具的 MVP。这就是 Eth-staking-smith 项目的诞生。
Eth-staking-smith 的组件图
Eth-staking-smith 可以用作 CLI 工具或 Rust 库,用于生成签名密钥和从新助记词派生的存款数据,或从现有助记词重新生成存款数据。实施这些用例是为了提供与 staking-deposit-cli 相同的功能,同时避免上述所有问题。
从新生成的助记词生成密钥的示例命令:
eth-staking-smith new-mnemonic --chain mainnet --keystore_password testtest --num_validators 1
从现有助记词生成密钥的示例命令:
eth-staking-smith existing-mnemonic --chain mainnet --keystore_password testtest --mnemonic "entire habit bottom mention spoil clown finger wheat motion fox axis mechanic country make garment bar blind stadium sugar water scissors canyon often ketchup" --num_validators 1 --withdrawal_credentials "0x0100000000000000000000000000000000000000000000000000000000000001"
对于这两种用例,Eth-staking-smith 将生成以下密钥材料:
私有签名密钥
如上所述,私有签名密钥是用于为验证器采取的任何操作提供签名的密钥。Eth-staking-smith 签名密钥的输出是在未加密的情况下完成的,因为在我们的用例中,我们使用远程 API 在生成后立即存储密钥材料。远程 API 对数据传输和静态数据实施加密。我们决定使 keystore 的使用成为可选的,但是 Eth-staking-smith 仍然可以为需要它的用户生成加密的 keystore。
例子:
{
…
"private_keys": [\
"6d446ca271eb229044b9039354ecdfa6244d1a11615ec1a46fc82a800367de5d"\
]
…
}
Keystore
keystore 是指定格式的私有签名密钥的加密版本 [6]。使用 eth-staking smith 生成密钥时,可以指定 keystore 密码,在这种情况下,将输出 keystore 数据。使用密钥派生函数(例如 scrypt
或 pbkdf2
),使用给定的密码和一组强大的内置派生参数派生解密密钥。下面的示例高亮显示了 function
字段,该字段显示了使用的密钥派生函数。keystore 是一种有用的替代方法,与将私有签名密钥存储在纯文本文件中相比,它不易受到攻击者的攻击,因为他们需要 keystore 文件以及用于解密该文件的密码。
例子:
{
…
"keystores": [\
{\
"crypto": {\
"checksum": {\
"function": "sha256",\
"message": "af14321c3083de535a0dd895b4e2fb156e6b0eda346120c8d7afb5277d3a489f",\
"params": {}\
},\
"cipher": {\
"function": "aes-128-ctr",\
"message": "8032685ad92a579e66328bbd6c747e41497dc6897c17cebbd83958394943924b",\
"params": {\
"iv": "da5699bb18ee7fea6095634a2fa05d18"\
}\
},\
"kdf": {\
"function": "pbkdf2",\
"message": "",\
"params": {\
"c": 262144,\
"dklen": 32,\
"prf": "hmac-sha256",\
"salt": "afb431f05b7fe02f253d9bc446ac686776541d38956fa6d39e14894f44e414d8"\
}\
}\
},\
"description": "",\
"name": null,\
"path": "m/12381/3600/0/0/0",\
"pubkey": "8844cebb34d10e0e57f3c29ada375dafe14762ab85b2e408c3d6d55ce6d03317660bca9f2c2d17d8fbe14a2529ada1ea",\
"uuid": "6dbae828-d0f0–42ed-9c06-d9079642ea08",\
"version": 4\
}\
],
…
}
助记词
用户传入的或生成的助记词将作为输出的一部分返回,以便用户可以安全地存储它。可以在参考资料 [7] 中找到有关助记词的更多信息。
例子:
{
…
"mnemonic": {
"seed": "ski interest capable knee usual ugly duty exercise tattoo subway delay upper bid forget say"
},
…
}
存款数据
最后,返回存款数据,该数据用于使用以太坊存款合约进行 32ETH 的存款以激活验证器。存款数据中最重要的字段之一是提款凭据。
默认情况下,提款凭据是从助记词派生的 BLS 地址,但是,存在用户可能想要用已经存在的凭据覆盖派生的提款凭据的用例。
BLS 地址格式称为 0x00
凭据,实际上将在启用提款后的某个时间被弃用。提供提款凭据的另一种替代方法是使用带有 0x01
前缀的旧版以太坊钱包地址。以太坊将从使用 0x00
(以前是 eth2)转向 0x01
执行(以前是 eth1)地址。要了解更多关于这一点,我们建议观看 Devcon 2022 [8] 的小组讨论,并查看以太坊规范 [4]。因此,Eth-staking-smith 允许用户传入一个 0x00
,0x01
执行提款凭据,以及一个执行地址来覆盖提款凭据。
带有 BLS 凭据的存款数据示例(--withdrawal_credentials 0x0045b91b2f60b88e7392d49ae1364b55e713d06f30e563f9f99e10994b26221d
)
{
…
"deposit_data": [\
{\
"amount": 32000000000,\
"deposit_cli_version": "2.3.0",\
"deposit_data_root": "2abc7681f73a01acbc1974ab47119766bf57d94f86a72828f8875295f5bd92de",\
"deposit_message_root": "bfd9d2c616eb570ad3fd4d4caf169b88f80490d8923537474bf1f6c5cec5e56d",\
"fork_version": "00001020",\
"network_name": "goerli",\
"pubkey": "8844cebb34d10e0e57f3c29ada375dafe14762ab85b2e408c3d6d55ce6d03317660bca9f2c2d17d8fbe14a2529ada1ea",\
"signature": "97c0ad0d4f721dc53f33a399dbf0ff2cab6f679f4efdcdaa9f8bdd22cd11b5e37c12fdd2cd29369b1b907a51573a9ef60f93d768fd2d47a99b5d55fe6516a87b9090e16c42f5a8fcbf91d24883359bffb074a02d6d4d7f6c3cd04c8e09f8dc02",\
"withdrawal_credentials": "0045b91b2f60b88e7392d49ae1364b55e713d06f30e563f9f99e10994b26221d"\
}\
],
…
}
带有执行地址的存款数据示例(--withdrawal_credentials 0x71C7656EC7ab88b098defB751B7401B5f6d8976F
)
{
…
"deposit_data": [\
{\
"amount": 32000000000,\
"deposit_cli_version": "2.3.0",\
"deposit_data_root": "95ac4064aabfdece592ddeaba83dc77cf095f2644c09e3453f83253a8b7e0ae1",\
"deposit_message_root": "6a0c14a9acd99ab4b9757f2ff2f41e04b44c0c53448fdf978c118841cd337582",\
"fork_version": "00001020",\
"network_name": "goerli",\
"pubkey": "8844cebb34d10e0e57f3c29ada375dafe14762ab85b2e408c3d6d55ce6d03317660bca9f2c2d17d8fbe14a2529ada1ea",\
"signature": "82effe6d57877b7d642775ae3d56f9411d41a85218b552c6318925c7ba23f7470ebe3a35045e2fc36b0e848e6f4ec1d503f2014dc5a7ad94a267f5b237f2475b5da9ff358fbd5a8e9f497f1db0cfb15624e686991d002077a6cd4efda8bdc67e",\
"withdrawal_credentials": "01000000000000000000000071c7656ec7ab88b098defb751b7401b5f6d8976f"\
}\
],
…
}
带有执行提款凭据的存款数据示例(--withdrawal_credentials 0x01000000000000000000000071c7656ec7ab88b098defb751B7401B5f6d8976F
)
{
…
"deposit_data": [\
{\
"amount": 32000000000,\
"deposit_cli_version": "2.3.0",\
"deposit_data_root": "95ac4064aabfdece592ddeaba83dc77cf095f2644c09e3453f83253a8b7e0ae1",\
"deposit_message_root": "6a0c14a9acd99ab4b9757f2ff2f41e04b44c0c53448fdf978c118841cd337582",\
"fork_version": "00001020",\
"network_name": "goerli",\
"pubkey": "8844cebb34d10e0e57f3c29ada375dafe14762ab85b2e408c3d6d55ce6d03317660bca9f2c2d17d8fbe14a2529ada1ea",\
"signature": "82effe6d57877b7d642775ae3d56f9411d41a85218b552c6318925c7ba23f7470ebe3a35045e2fc36b0e848e6f4ec1d503f2014dc5a7ad94a267f5b237f2475b5da9ff358fbd5a8e9f497f1db0cfb15624e686991d002077a6cd4efda8bdc67e",\
"withdrawal_credentials": "01000000000000000000000071c7656ec7ab88b098defb751b7401b5f6d8976f"\
}\
],
…
}
下面我们展示了由 Eth-staking-smith 生成的密钥材料的完整示例输出:
命令:
eth-staking-smith existing-mnemonic --chain goerli --keystore_password testtest --mnemonic "ski interest capable knee usual ugly duty exercise tattoo subway delay upper bid forget say" --num_validators 1
输出:
{
"deposit_data": [\
{\
"amount": 32000000000,\
"deposit_cli_version": "2.3.0",\
"deposit_data_root": "2abc7681f73a01acbc1974ab47119766bf57d94f86a72828f8875295f5bd92de",\
"deposit_message_root": "bfd9d2c616eb570ad3fd4d4caf169b88f80490d8923537474bf1f6c5cec5e56d",\
"fork_version": "00001020",\
"network_name": "goerli",\
"pubkey": "8844cebb34d10e0e57f3c29ada375dafe14762ab85b2e408c3d6d55ce6d03317660bca9f2c2d17d8fbe14a2529ada1ea",\
"signature": "97c0ad0d4f721dc53f33a399dbf0ff2cab6f679f4efdcdaa9f8bdd22cd11b5e37c12fdd2cd29369b1b907a51573a9ef60f93d768fd2d47a99b5d55fe6516a87b9090e16c42f5a8fcbf91d24883359bffb074a02d6d4d7f6c3cd04c8e09f8dc02",\
"withdrawal_credentials": "0045b91b2f60b88e7392d49ae1364b55e713d06f30e563f9f99e10994b26221d"\
}\
],
"keystores": [\
{\
"crypto": {\
"checksum": {\
"function": "sha256",\
"message": "af14321c3083de535a0dd895b4e2fb156e6b0eda346120c8d7afb5277d3a489f",\
"params": {}\
},\
"cipher": {\
"function": "aes-128-ctr",\
"message": "8032685ad92a579e66328bbd6c747e41497dc6897c17cebbd83958394943924b",\
"params": {\
"iv": "da5699bb18ee7fea6095634a2fa05d18"\
}\
},\
"kdf": {\
"function": "pbkdf2",\
"message": "",\
"params": {\
"c": 262144,\
"dklen": 32,\
"prf": "hmac-sha256",\
"salt": "afb431f05b7fe02f253d9bc446ac686776541d38956fa6d39e14894f44e414d8"\
}\
}\
},\
"description": "",\
"name": null,\
"path": "m/12381/3600/0/0/0",\
"pubkey": "8844cebb34d10e0e57f3c29ada375dafe14762ab85b2e408c3d6d55ce6d03317660bca9f2c2d17d8fbe14a2529ada1ea",\
"uuid": "6dbae828-d0f0–42ed-9c06-d9079642ea08",\
"version": 4\
}\
],
"mnemonic": {
"seed": "ski interest capable knee usual ugly duty exercise tattoo subway delay upper bid forget say"
},
"private_keys": [\
"6d446ca271eb229044b9039354ecdfa6244d1a11615ec1a46fc82a800367de5d"\
]
}
由于将密钥材料写入磁盘对我们来说是一个主要的安全漏洞,因此 Eth-staking-smith 通过不在磁盘上写入任何文件来完全消除此问题。
为了避免繁重的工作并从头开始重新创建加密原语,我们正在重用 lighthouse 客户端实现 [9] 中的密钥生成功能,该功能建立在 blst 之上——BLS12–381 签名库 [10],目前正在接受形式化验证。
对于熵收集,进行了一项自定义:Eth-staking-smith 通过在 Linux 上使用 getrandom()
将熵收集推迟到操作系统,从而利用了 Linux 最新的随机性方法。
最后,由于大规模密钥生成对我们来说使用 staking-deposit-cli 速度非常慢,因此我们主动为用户添加了额外的参数,以根据其特定用例调整性能<>安全性参数。
根据我们的用例,我们的 API 不需要 keystore 文件,只需要原始格式的私钥。因此,我们使用户可以选择不生成 keystore,以提高性能。可以通过省略 --keystore_password
参数来完成此操作,如下所示:
eth-staking-smith new-mnemonic --chain goerli --num_validators 1
我们测量到省略 keystore 可以将密钥生成过程加快 99%。我们在 Eth-staking-smith 中体验到的密钥生成性能始终低于一秒,并且根据硬件和平台的不同,略有差异。
如果用户需要 keystore 文件以进行冗余,则可以选择通过选择其他密钥派生函数来加快 keystore 生成过程。默认情况下,Eth-staking-smith 将使用 pbkdf2
来派生解密密钥,以实现更好的性能。还可以选择使用 scrypt
,它可以提供更好的安全性,但是,随之而来的是更差的性能。可以通过使用 --kdf
参数选择密钥派生函数来完成此操作,如下所示:
eth-staking-smith new-mnemonic --chain goerli --keystore_password testtest --num_validators 1 --kdf scrypt
如上所述,先前指定了 BLS (0x00) 提款地址的用户需要向信标链发出请求,以更新其验证器的提款地址以指向执行地址。要执行此操作,用户将需要 BLS 提款密钥助记词短语。完成后,提款将自动在执行地址上进行资助。
Eth-staking-smith 使能够生成已签名的 BLS_TO_EXECUTION_CHANGE
消息,用户可以将其发送到信标链以更新其提款地址。
eth-staking-smith bls-to-execution-change --chain mainnet --mnemonic "entire habit bottom mention spoil clown finger wheat motion fox axis mechanic country make garment bar blind stadium sugar water scissors canyon often ketchup" --validator_index 0 --withdrawal_credentials "0x0045b91b2f60b88e7392d49ae1364b55e713d06f30e563f9f99e10994b26221d" --execution_address "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"
用户可以使用以下响应向信标节点发出请求:
curl -H "Content-Type: application/json" -d '{ "message": { "validator_index": 0, "from_bls_pubkey": "0x0045b91b2f60b88e7392d49ae1364b55e713d06f30e563f9f99e10994b26221d", "to_execution_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F" }, "signature": "0x9220e5badefdfe8abc36cae01af29b981edeb940ff88c438f72c8af876fbd6416138c85f5348c5ace92a081fa15291aa0ffb856141b871dc807f3ec2fe9c8415cac3d76579c61455ab3938bc162e139d060c8aa13fcd670febe46bf0bb579c5a" }' http://localhost:3500/eth/v1/beacon/pool/bls_to_execution_change
在本文中,我们解释了以太坊信标链块验证的基础知识,该过程中涉及的密钥材料,并介绍了我们在 Chorus One 创建的 Proof-of-Stake 密钥管理自动化工具。
我们希望该工具对我们的一些读者有用,特别是那些使用 Rust 进行区块链自动化工作的人。它也是开源的,我们将欢迎 Github 上的错误报告和 pull request。
如果读者有兴趣使用基于该自动化的 OPUS 验证即服务 API,欢迎加入私有 Beta 版的候补名单,请通过 sales@chorus.one 联系。
[1] https://kb.beaconcha.in/ethereum-2-keys
[2] https://eth2book.info/altair/part2/building_blocks/signatures#aggregation
[3] https://learnblockchain.cn/docs/eips/EIPS/eip-4895
[4] https://notes.ethereum.org/@GW1ZUbNKR5iRjjKYx6_dJQ/Skxf3tNcg_
[5] https://github.com/ethereum/consensus-specs/blob/dev/specs/capella/beacon-chain.md
[6] https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2335.md
[7] https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
[8] https://www.youtube.com/watch?v=zf7HJT_DMFw&feature=youtu.be
[9] https://github.com/sigp/lighthouse
[10] https://github.com/supranational/blst
- 原文链接: medium.com/chorus-one/et...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!