跳转至主要内容
Change page

Web3 密钥存储定义

页面最后更新: 2025年10月21日

为了让应用程序在以太坊上运行,你可以使用 web3.js 程序库提供的 web3 对象。 它在底层通过远程过程调用与本地节点通信。 web3opens in a new tab 可以与任何公开远程过程调用 (RPC) 层的以太坊节点协同工作。

web3 包含 eth 对象 - web3.eth。

1var fs = require("fs")
2var recognizer = require("ethereum-keyfile-recognizer")
3
4fs.readFile("keyfile.json", (err, data) => {
5 var json = JSON.parse(data)
6 var result = recognizer(json)
7})
8
9/** result
10 * [ 'web3', 3 ] web3 (v3) 密钥文件
11 * [ 'ethersale', undefined ] Ethersale 密钥文件
12 * null 无效密钥文件
13 */
显示全部

本文介绍 Web3 密钥存储定义的第 3 版

定义

文件的实际编码和解码与第 1 版相比基本没有变化,只是加密算法不再固定为 AES-128-CBC(AES-128-CTR 目前是最低要求)。 大部分含义/算法与版本 1 相似,但 mac 除外,它是派生密钥的次左边 16 个字节与完整的 ciphertext 拼接后内容的 SHA3 (keccak-256) 哈希值。

密钥文件直接存储在 ~/.web3/keystore(类 Unix 系统)和 ~/AppData/Web3/keystore(Windows 系统)中。 它们可以任意命名,但一个好的约定是 <uuid>.json,其中 <uuid> 是分配给密钥的 128 位 UUID(密钥地址的隐私保护代理)。

所有这些文件都有一个关联的密码。 要派生给定 .json 文件的密钥,首先派生该文件的加密密钥;此操作通过获取该文件的密码,并将其传递到由 kdf 键描述的密钥派生函数来完成。 KDF 函数中依赖于 KDF 的静态和动态参数在 kdfparams 键中描述。

PBKDF2 必须得到所有符合最低标准的实现的支持,表示为:

  • kdfpbkdf2

对于 PBKDF2,kdfparams 包括:

  • prf:必须是 hmac-sha256(将来可能会扩展);
  • c:迭代次数;
  • salt:传递给 PBKDF 的盐;
  • dklen:派生密钥的长度。 必须 >= 32。

派生出文件的密钥后,应该通过派生 MAC 来验证它。 MAC 的计算方法是:将派生密钥的次左边 16 个字节与 ciphertext 键的内容拼接,形成一个字节数组,然后计算该数组的 SHA3 (keccak-256) 哈希值,即:

1KECCAK(DK[16..31] ++ <ciphertext>)

(其中 ++ 是拼接运算符)

应将此值与 mac 键的内容进行比较;如果二者不同,则应请求输入其他密码(或取消操作)。

文件密钥验证通过后,即可使用由 cipher 键指定、并由 cipherparams 键参数化的对称加密算法,来解密密文(即文件中 ciphertext 键的值)。 如果派生密钥的大小和算法密钥的大小不匹配,则用零来填充。派生密钥的最右边字节应该作为算法的密钥。

所有符合最低标准的实现必须支持 AES-128-CTR 算法,表示为:

  • cipher: aes-128-ctr

该密码需要以下参数,作为 cipherparams 密钥的密钥:

  • iv:加密算法的 128 位初始化向量。

加密算法的密钥是派生密钥最左边的 16 字节,即 DK[0..15]

密钥的创建/加密本质上应是这些指令的逆向操作。 确保 uuidsaltiv 确实是随机的。

除了作为版本“硬”标识符的 version 字段外,实现方也可以使用 minorversion 来跟踪对格式的较小的、非破坏性的更改。

测试向量

详细信息:

  • 地址008aeeda4d805471df9b2a5b0f38a0c3bcba786b
  • ICAPXE542A5PZHH8PYIZUBEJEO0MFWRAPPIL67
  • UUID3198bc9c-6672-5ab3-d9954942343ae5b6
  • 密码testpassword
  • 机密7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d

PBKDF2-SHA-256

使用 AES-128-CTRPBKDF2-SHA-256 的测试向量:

~/.web3/keystore/3198bc9c-6672-5ab3-d9954942343ae5b6.json 的文件内容:

1{
2 "crypto": {
3 "cipher": "aes-128-ctr",
4 "cipherparams": {
5 "iv": "6087dab2f9fdbbfaddc31a909735c1e6"
6 },
7 "ciphertext": "5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46",
8 "kdf": "pbkdf2",
9 "kdfparams": {
10 "c": 262144,
11 "dklen": 32,
12 "prf": "hmac-sha256",
13 "salt": "ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd"
14 },
15 "mac": "517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2"
16 },
17 "id": "3198bc9c-6672-5ab3-d995-4942343ae5b6",
18 "version": 3
19}
显示全部

中间值

派生密钥f06d69cdc7da0faffb1008270bca38f5e31891a3a773950e6d0fea48a7188551 MAC 正文e31891a3a773950e6d0fea48a71885515318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46 MAC517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2 加密密钥f06d69cdc7da0faffb1008270bca38f5

Scrypt

使用 AES-128-CTR 和 Scrypt 的测试向量:

1{
2 "crypto": {
3 "cipher": "aes-128-ctr",
4 "cipherparams": {
5 "iv": "740770fce12ce862af21264dab25f1da"
6 },
7 "ciphertext": "dd8a1132cf57db67c038c6763afe2cbe6ea1949a86abc5843f8ca656ebbb1ea2",
8 "kdf": "scrypt",
9 "kdfparams": {
10 "dklen": 32,
11 "n": 262144,
12 "p": 1,
13 "r": 8,
14 "salt": "25710c2ccd7c610b24d068af83b959b7a0e5f40641f0c82daeb1345766191034"
15 },
16 "mac": "337aeb86505d2d0bb620effe57f18381377d67d76dac1090626aa5cd20886a7c"
17 },
18 "id": "3198bc9c-6672-5ab3-d995-4942343ae5b6",
19 "version": 3
20}
显示全部

中间值

派生密钥7446f59ecc301d2d79bc3302650d8a5cedc185ccbb4bf3ca1ebd2c163eaa6c2d MAC 正文edc185ccbb4bf3ca1ebd2c163eaa6c2ddd8a1132cf57db67c038c6763afe2cbe6ea1949a86abc5843f8ca656ebbb1ea2 MAC337aeb86505d2d0bb620effe57f18381377d67d76dac1090626aa5cd20886a7c 加密密钥7446f59ecc301d2d79bc3302650d8a5c

与版本 1 的改动

此版本修复了与此处opens in a new tab发布的版本 1 的几处不一致。 简短来说,它们是:

  • 大小写不合理和不一致(scrypt 小写,Kdf 大小写混合,MAC 大写)。
  • 地址不必要并损害了隐私。
  • Salt 本质上是密钥派生函数的一个参数,因此应与该函数相关联,而不是与整个加密机制相关联。
  • SaltLen 是不必要的(直接从 Salt 派生即可)。
  • 给出了密钥派生函数,但加密算法是硬性指定的。
  • Version 本质上是一个数字,然而却是一个字符串(结构化版本管理可以用一个字符串来实现,但对于一个很少变化的配置文件格式来说,可以认为是超出了范围)。
  • KDFcipher 在概念上是同级关系,但组织方式却不同。
  • MAC 是通过一段与空白字符无关的数据计算的(!)

我们对格式进行了修改,得到了以下文件,其功能和之前链接页面上的示例一样:

1{
2 "crypto": {
3 "cipher": "aes-128-cbc",
4 "ciphertext": "07533e172414bfa50e99dba4a0ce603f654ebfa1ff46277c3e0c577fdc87f6bb4e4fe16c5a94ce6ce14cfa069821ef9b",
5 "cipherparams": {
6 "iv": "16d67ba0ce5a339ff2f07951253e6ba8"
7 },
8 "kdf": "scrypt",
9 "kdfparams": {
10 "dklen": 32,
11 "n": 262144,
12 "p": 1,
13 "r": 8,
14 "salt": "06870e5e6a24e183a5c807bd1c43afd86d573f7db303ff4853d135cd0fd3fe91"
15 },
16 "mac": "8ccded24da2e99a11d48cda146f9cc8213eb423e2ea0d8427f41c3be414424dd",
17 "version": 1
18 },
19 "id": "0498f19a-59db-4d54-ac95-33901b4f1870",
20 "version": 2
21}
显示全部

与版本 2 的改动

第 2 版是早期 C++ 实现的版本,有很多漏洞。 所有重要内容保持不变。

本文对你有帮助吗?