Web3密钥存储定义规范了一种标准化的方法,用于加密和存储以太坊私钥,主要由钱包软件(如 MetaMask、Geth)使用。本文档将详细介绍其背景、文件结构、加密与解密流程,以及代码示例。
1. 背景与目的
1.1 什么是 Web3 密钥存储?
定义:Web3 密钥存储是一种 JSON 格式的文件规范,用于安全存储以太坊账户的私钥。
目的:
- 保护私钥免受未经授权的访问。
- 便于跨钱包软件移植私钥。
使用场景:
- 用户通过密码加密私钥,生成密钥存储文件。
- 钱包软件(如 Geth)读取文件,解密后访问私钥。
1.2 历史背景
- 起源:由以太坊社区提出,最初用于 Geth 客户端。
- 标准化:现已成为以太坊生态中的事实标准,许多钱包软件(如 MetaMask、MyEtherWallet)遵循该规范。
2. 密钥存储文件结构
2.1 JSON 格式
- 文件扩展名:通常为
.json
- 典型文件名:
UTC--YYYY-MM-DDTHH:MM:SS.SSSZ--<UUID>
- UTC 时间戳:文件创建时间。
- UUID:唯一标识。
2.2 JSON 字段解析
以下是密钥存储文件的核心字段:
{
"version": 3,
"id": "7e41e9e1-b477-44e2-a6ae-be50625b0a8f",
"address": "aa8fb2d7630a64715577e399ff3ed5f5c4938389",
"crypto": {
"ciphertext": "d2b4bf81bd0c7ebbcfde07c8d4f3057f5405eabf897f0a01566a3fb9",
"cipherparams": {
"iv": "c22c0d01e5f11ac2ea6ddd78e2578f22"
},
"cipher": "aes-128-ctr",
"kdf": "scrypt",
"kdfparams": {
"dklen": 32,
"salt": "c3b875d218ca0e0eafe0e561a31747f6e735f7e0bc9d3a0aa1f7ec22c10e65de",
"n": 8192,
"r": 8,
"p": 1
},
"mac": "f123d0ae24dde42f07a2512c54f0d69191577ae8fb1ab92b6a5f1e64f0d9e5e8"
}
}
字段解析:
version
:当前版本为3
。id
:唯一标识该密钥存储文件。address
:以太坊账户地址(无0x
前缀)。crypto
:包含加密相关数据。ciphertext
:加密的私钥。cipherparams.iv
:初始化向量。cipher
:加密算法(如aes-128-ctr
)。kdf
:密钥派生函数(如scrypt
或pbkdf2
)。mac
:消息认证码,确保数据完整性。
3. 加密与解密流程
3.1 加密流程
- 用户输入密码。
- 密钥派生:使用 KDF(如
scrypt
)从密码生成密钥。 - 加密私钥:
- 取派生密钥前 16 字节进行 AES-128-CTR 加密。
- 生成
ciphertext
。
- 生成 MAC:
mac = keccak256(derived_key[16:32] || ciphertext)
- 保存 JSON 文件。
3.2 解密流程
- 读取 JSON 文件。
- 密钥派生:根据
kdfparams
重新生成derived_key
。 - 验证 MAC,确保数据未被篡改。
- 解密私钥。
4. 代码示例
4.1 生成密钥存储文件(JavaScript)
const password = "your_password_here";
const privateKey = "your_private_key_in_hex";
const salt = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
const kdfParams = { n: 8192, r: 8, p: 1, dklen: 32 };
const derivedKey = scrypt(password, salt, kdfParams.n, kdfParams.r, kdfParams.p, kdfParams.dklen);
const cipherKey = derivedKey.slice(0, 16);
const cipher = crypto.createCipheriv('aes-128-ctr', cipherKey, iv);
const ciphertext = Buffer.concat([cipher.update(privateKey, 'hex'), cipher.final()]);
const mac = keccak256(Buffer.concat([derivedKey.slice(16, 32), ciphertext]));
4.2 解密密钥存储文件
const keystore = JSON.parse(fs.readFileSync('keystore.json'));
const { crypto } = keystore;
const derivedKey = scrypt(password, Buffer.from(crypto.kdfparams.salt, 'hex'), ...);
const computedMac = keccak256(Buffer.concat([derivedKey.slice(16, 32), Buffer.from(crypto.ciphertext, 'hex')]));
if (!computedMac.equals(Buffer.from(crypto.mac, 'hex'))) throw new Error('Invalid password');
const cipherKey = derivedKey.slice(0, 16);
const decipher = crypto.createDecipheriv('aes-128-ctr', cipherKey, Buffer.from(crypto.cipherparams.iv, 'hex'));
const privateKey = Buffer.concat([decipher.update(Buffer.from(crypto.ciphertext, 'hex')), decipher.final()]);
5. 安全性与注意事项
5.1 安全性特性
- AES-128-CTR 提供强加密。
- scrypt/PBKDF2 增加暴力破解难度。
- MAC 机制 防止密文篡改。
5.2 注意事项
- 使用强密码,防止被破解。
- 合理设置 KDF 参数,如
n=8192
平衡安全性与性能。 - 文件存储安全,避免泄露。
6. 总结
- Web3 密钥存储 是一种标准化的私钥管理方案。
- JSON 结构 规范化密钥存储方式。
- 加密流程 采用 AES-128-CTR + KDF + MAC 保护私钥安全。
- 代码示例 提供实现细节,方便开发者参考。
如需更深入探讨某部分(如优化 KDF 参数或 Rust 实现),请告诉我!