钱包
概念
在了解以太坊钱包在密码学应用之前,先了解下以太坊钱包的本质,从本质出发更容易理解对安全要求的由来。
以太坊钱包可以理解为:个人数字资产的金库和数字资产交易中心的入口。
它的核心功能分为两大块账号管理和资产管理,账号管理是钱包的“军事禁区”,资产管理是钱包的“营业大厅”。
设计哲学
以太坊钱包的设计哲学是:用一个结构精巧的多层管理系统,让数字资产管理既像使用微信钱包一样简单,又像管理瑞士银行账户一样安全。
以太坊钱包产品是钱包的管理器,而钱包又是账户的管理器。
以MetaMask为例,在上面可以添加很多钱包用于不同的用途,同一个钱包下可以对应有多个账户。
这样的分层结构设计便于用户统一管理和分类使用。
安全策略
在安全方面,一组助记词对应一个钱包,一个钱包下的不同账户分别对应一个地址和一堆密钥(公钥和私钥),但这对密钥是从同一个主私钥派生出来的。
安全层级是一个完整的防御体系:
- 一级安全:助记词生成与备份(离线物理存储)
- 二级安全:私钥加密存储(钱包密码保护)
- 三级安全:账户派生分离(BIP-32标准)
- 四级安全:交易签名确认(每次手动确认)
密码学贯穿整个安全体系:
助记词生成使用SHA-256哈希;
私钥加密使用scrypt和AES;
账户派生使用HMAC-SHA512和椭圆曲线加密;
交易签名使用ECDSA算法。
其中,二级安全的核心主要是对私钥的加密保护。
密码学原理
第一层:助记词熵 – 确保初始随机性足够
以太坊钱包的助记词单词取自于BIP-39词表,该表使用2048个英文单词的预定义列表。
每个单词的信息量:log₂(2048) = 11位(根据信息论的基本思想:如果一个事件有N种等可能的结果,那么当我们得知其中一个结果发生时,我们就获得了log₂(N)比特的信息。)
12个单词:11*12=132位(128位原始熵、前4位校验和)
那么,它的安全强度有2^128。
实际需要尝试:2^128≈3.4*10^38 次,
攻击时间估算(假设每秒10亿次尝试): 3.4 × 10³⁸ ÷ 10⁹ ÷ (365×24×3600) ≈ 1.08 × 10²² 年 (宇宙年龄约1.38 × 10¹⁰年)
第二层:密码派生 – scrypt抵抗暴力破解
以太坊钱包使用scrypt密钥派生函数将用户密码转换为加密密钥,这是专门设计来抵抗大规模硬件攻击的算法。
第三层:对称加密 – AES保护存储中的私钥
以太坊钱包使用AES-128-CTR(高级加密标准)对称加密算法来保护存储在keystore文件中的私钥。
AES-128-CTR模式:使用128位密钥的计数器模式,将分组密码转换为流密码
初始化向量(IV):每个keystore使用随机IV,确保相同明文产生不同密文
密钥空间:2¹²⁸ ≈ 3.4×10³⁸ 种可能密钥
第四层:完整性验证 – MAC防止数据篡改
以太坊钱包使用Keccak-256哈希函数生成消息认证码(MAC),确保keystore文件的完整性和真实性。
MAC计算:MAC = keccak256(MAC密钥 || 密文)
验证机制:解密时重新计算MAC并与存储值比较
哈希特性:抗碰撞性、抗原像攻击、抗第二原像攻击
加密过程详解
所以对私钥的存储要执行非常严格的加密过程,结合一个钱包使用实例来理解对安全性要求极高的加密过程。
加密的过程可以简单理解:
- 使用mnemonic方法生成助记词;
- 从助记词生成私钥;
- 用密码结合复杂的密码学加密私钥 → keystore.json
- 返回”成功”
接下来,结合具体代码理解这一过程
1. 生成助记词
def generate_mnemonic(self):
"""生成一个12词的助记词"""
return Mnemonic("english").generate(128)
系统生成12个随机的英文单词,就像银行给你12个”安全词”。
这些单词能重新生成你的私钥(非常重要!)
2. 导入并加密
导入
def import_wallet_and_encrypt(self, secret_value, password):
"""
导入钱包(助记词或私钥)并加密保存为Keystore。
"""
判断输入类型
# 1. 尝试作为助记词导入
if len(secret_value.split()) >= 12:
# 这是一个助记词
self.account = Account.from_mnemonic(secret_value)
# 2. 尝试作为私钥导入
elif re.match(r"^(0x)?[0-9a-fA-F]{64}$", secret_value):
# 这是一个私钥
self.account = Account.from_key(secret_value)
如果是12个单词→当助记词处理
如果是64个16进制字符→当私钥处理
两者都能生成以太坊账户
三、加密存储
# 3. 加密账户并保存Keystore
encrypted_json = Account.encrypt(self.account.key, password)
with open(self.keystore_file, "w") as f:
json.dump(encrypted_json, f)
这一行代码背后发生了什么?
Account.encrypt(self.account.key, password) 做了以下事情:
假设输入:
- 私钥:0x2a4f5c…(你的财产证明)
- 密码:MyDog2024!(你设的密码)
过程:
1. 生成“随机调料”(盐值):salt = 随机生成的一串字符(比如:x9kP…)
2. 搅拌密码(scrypt算法):MyDog2024!+ x9kP… (盐值)→ 搅拌 30 万次 → 得到“复杂密码”
3. 加密私钥(AES算法):用“复杂密码”加密你的私钥
4.做防伪标签(MAC):用“复杂密码”的一部分 + 加密后的私钥 → 生成防伪码
5. 打包所有东西
{“加密的私钥”:“…乱码…",
"盐值”:“x9kp…",
“搅拌方法”:“慢速搅拌30万次”,
“防伪标签”:“…",
"其他参数”:“…"
}
四、保存文件
with open(self.keystore_file, "w") as f:
json.dump(encrypted_json, f)
把上面的JSON对象保存到keystore.json文件;
这个文件可以随便备份,因为没有密码打不开。
这一过程,就是把私钥放入了一个保险箱,再给这个保险箱加了一个封条。
这个保险箱就是基于你设置的密码运用scrypt算法得到复杂密码,之后运用AES算法将私钥加密(放进保险箱),然后运用MAC算法,将复杂密码的一部分+加密后的私钥生成防伪码(封条)。


