Day 2 账户体系与密钥管理
掌握账户创建、密钥存储和助记词钱包的使用。
学习目标
- 理解 Aeternity 账户地址的编码规则
- 掌握私钥、公钥与地址的关系
- 熟练使用 Account 类进行账户管理
- 掌握助记词钱包的使用方法
1. 账户地址编码
1.1 地址格式
| 前缀 | 类型 | 编码 | 示例 |
|---|---|---|---|
ak_ | 账户地址 | Base58 | ak_2swhLkgB... |
ct_ | 合约地址 | Base58 | ct_2AfnEfC... |
ok_ | 预言机地址 | Base58 | ok_2swhLkgB... |
nm_ | 域名 ID | Base58 | nm_2sFnPH... |
th_ | 交易哈希 | Base58 | th_2AfnEfC... |
kh_ | 关键块哈希 | Base58 | kh_2sFnPH... |
cb_ | 字节码 | Base64 | cb_+QEWA... |
1.2 地址生成流程
┌─────────────────────────────────────────────────────────────┐
│ 地址生成流程 │
├─────────────────────────────────────────────────────────────┤
│ 随机数 (32 字节) │
│ │ │
│ ▼ │
│ ED25519 私钥 (64 字节) │
│ │ │
│ ▼ │
│ ED25519 公钥 (32 字节) │
│ │ │
│ ▼ │
│ Base58Check 编码 │
│ │ │
│ ▼ │
│ 添加 "ak_" 前缀 → ak_2swhLkgBPeeADxV... │
└─────────────────────────────────────────────────────────────┘
2. Keystore 加密机制
2.1 加密标准
| 组件 | 算法 | 说明 |
|---|---|---|
| 密钥派生 | Argon2id | 抗 GPU 攻击的密码哈希 |
| 对称加密 | XSalsa20-Poly1305 | NaCl SecretBox |
| 认证 | Poly1305 MAC | 消息认证码 |
3. BIP39/BIP44 标准
助记词是一组易于记忆的单词,用于备份和恢复钱包:
- 支持 12/15/18/21/24 个单词
- 从 2048 个英文单词中选取
- 包含校验和
BIP44 派生路径
m / purpose' / coin_type' / account' / change' / address_index'
m / 44' / 457' / 0' / 0' / 0'
参数说明:
- purpose': 固定为 44(BIP44 标准)
- coin_type': 457(Aeternity 的注册号)
- account': 账户索引(0, 1, 2...)
- change': 固定为 0
- address_index': 地址索引(0, 1, 2...)
4. 实践任务
任务 2.1: 生成和管理账户
from aeternity.signing import Account
from aeternity.identifiers import ACCOUNT_API_FORMAT, ACCOUNT_SOFIA_FORMAT
# 生成新账户
account = Account.generate()
# 获取地址(不同格式)
api_address = account.get_address()
sophia_address = account.get_address(ACCOUNT_SOFIA_FORMAT)
print(f"=== 新账户信息 ===")
print(f"API 地址: {api_address}")
print(f"Sophia 地址: {sophia_address}")
# 获取私钥(十六进制)
private_key = account.get_secret_key()
print(f"\n私钥: {private_key[:32]}...{private_key[-32:]}")
print(f"私钥长度: {len(private_key)} 字符 ({len(private_key)//2} 字节)")
# 从私钥恢复账户
recovered = Account.from_secret_key_string(private_key)
print(f"\n=== 恢复验证 ===")
print(f"恢复的地址: {recovered.get_address()}")
print(f"地址匹配: {recovered.get_address() == api_address}")
任务 2.2: 使用 Keystore
from aeternity.signing import Account
import os
import json
# 生成账户
account = Account.generate()
original_address = account.get_address()
print(f"=== 原始账户 ===")
print(f"地址: {original_address}")
# 保存到 Keystore 文件
keystore_path = "test_wallet.json"
password = "SecurePassword123!"
account.save_to_keystore_file(keystore_path, password)
print(f"\n✅ Keystore 已保存到: {keystore_path}")
# 查看 Keystore 内容
with open(keystore_path) as f:
keystore = json.load(f)
print(f"\nKeystore 结构:")
print(f" 公钥: {keystore.get('public_key', 'N/A')[:30]}...")
print(f" 加密算法: {keystore['crypto']['symmetric_alg']}")
print(f" 密钥派生: {keystore['crypto']['kdf']}")
# 从 Keystore 加载
loaded_account = Account.from_keystore(keystore_path, password)
loaded_address = loaded_account.get_address()
print(f"\n=== 恢复验证 ===")
print(f"加载的地址: {loaded_address}")
print(f"地址匹配: {loaded_address == original_address}")
# 测试错误密码
try:
Account.from_keystore(keystore_path, "wrong_password")
except ValueError as e:
print(f"\n✅ 错误密码被正确拒绝")
# 清理测试文件
os.remove(keystore_path)
任务 2.3: 创建助记词钱包
from aeternity.wallet import MnemonicWallet
# 生成新钱包
wallet = MnemonicWallet.generate()
print(f"=== 新助记词钱包 ===")
print(f"助记词: {wallet.mnemonic}")
print(f"\n⚠️ 请安全保存助记词!任何拥有助记词的人都可以控制你的资产!")
print(f"\n主地址: {wallet.address}")
# 获取主账户
master_account = wallet.account
print(f"主账户私钥: {master_account.get_secret_key()[:32]}...")
# 从助记词恢复
print(f"\n=== 恢复测试 ===")
recovered_wallet = MnemonicWallet.from_mnemonic(wallet.mnemonic)
print(f"恢复后地址: {recovered_wallet.address}")
print(f"地址匹配: {recovered_wallet.address == wallet.address}")
任务 2.4: HD 钱包派生
from aeternity.hdwallet import HDWallet
# 创建 HD 钱包
wallet = HDWallet()
print(f"=== HD 钱包 ===")
print(f"助记词: {wallet.mnemonic}")
print(f"\n派生路径格式: m/44'/457'/account'/0'/address'")
# 获取主账户 (m/44'/457'/0'/0'/0')
master_account = wallet.get_master_account()
print(f"\n主账户:")
print(f" 路径: m/44'/457'/0'/0'/0'")
print(f" 地址: {master_account.get_address()}")
# 派生多个子账户
print(f"\n派生子账户:")
for i in range(5):
path, account = wallet.derive_child(account_index=i, address_index=0)
print(f" {path}")
print(f" → {account.get_address()}")
任务 2.5: 消息签名和验证
from aeternity.signing import Account, is_signature_valid
# 生成账户
account = Account.generate()
address = account.get_address()
print(f"=== 消息签名 ===")
print(f"账户地址: {address}")
# 签名消息
message = b"Hello, Aeternity Blockchain!"
signature = account.sign(message)
print(f"\n原始消息: {message.decode()}")
print(f"签名: {signature.hex()[:64]}...")
print(f"签名长度: {len(signature)} 字节")
# 使用 Account.verify 验证
print(f"\n=== 验证签名 ===")
try:
account.verify(message, signature)
print("✅ 签名验证成功 (Account.verify)")
except Exception as e:
print(f"❌ 签名验证失败: {e}")
# 使用独立函数验证
is_valid = is_signature_valid(address, signature, message)
print(f"✅ is_signature_valid 结果: {is_valid}")
# 验证错误的消息
print(f"\n=== 篡改检测 ===")
wrong_message = b"Tampered message"
is_valid = is_signature_valid(address, signature, wrong_message)
print(f"篡改消息验证结果: {is_valid} (预期: False)")
知识检查点
完成 Day 2 后,你应该能够:
- 解释地址编码规则(ak_ 前缀、Base58)
- 生成和恢复账户
- 使用 Keystore 加密存储私钥
- 创建和使用助记词钱包
- 派生 HD 钱包子账户
- 签名和验证消息
本页目录
预计学习时间: 2-3 小时