BIP39 助记词生成 ETH 地址靠 secp256k1 + keccak256,走 Solana 就完全换了一套——Ed25519 + SLIP-0010,最后不做 hash,直接 Base58 编码公钥。
全流程
助记词 (Mnemonic)
│ PBKDF2-HMAC-SHA512
▼
Seed (64 字节)
│ SLIP-0010 (Ed25519)
▼
Master Key
│ 按路径 m/44'/501'/0'/0' 派生
▼
Ed25519 私钥 (32 字节)
│ Ed25519 公钥算法
▼
公钥 (32 字节)
│ Base58 编码
▼
Solana 地址
和 BTC/ETH 唯一相同的只有第一步”助记词转 seed”,之后全变了。
第一步:助记词 → seed
标准 BIP39,PBKDF2-HMAC-SHA512:
password = 助记词字符串
salt = "mnemonic" + passphrase
iters = 2048
output = 64 字节
Python:
from mnemonic import Mnemonic
mnemo = Mnemonic("english")
seed = mnemo.to_seed(
"abandon abandon abandon abandon abandon abandon "
"abandon abandon abandon abandon abandon about",
passphrase="",
)
print(seed.hex())
第二步:seed → Master Key(SLIP-10 Ed25519)
Solana 用 SLIP-0010(Ed25519 版本),和 BIP32 的 secp256k1 分道扬镳:
I = HMAC-SHA512(key="ed25519 seed", data=seed)
IL = master private key (32 字节)
IR = master chain code (32 字节)
第三步:派生路径
Solana 默认路径:
m/44'/501'/0'/0'
44':BIP44501':Solana 的 coin type0':account0':change
每一级都是 hardened derivation(' 表示 + 2³¹)。Ed25519 只支持 hardened 派生,非 hardened 会直接报错。
第四步:公钥 & 地址
私钥经 Ed25519 算出 32 字节公钥。地址 = Base58(公钥),就这么简单:
- 没有 SHA-256 double hash
- 没有 RIPEMD-160
- 没有 keccak
- 没有 checksum(Base58 本身没自带校验,也没有像 BTC 那样附 4 字节 hash)
Python 一把梭
bip_utils 把上面所有细节封好了:
from bip_utils import Bip39SeedGenerator, Bip44, Bip44Coins
mnemonic = ("abandon abandon abandon abandon abandon abandon "
"abandon abandon abandon abandon abandon about")
seed = Bip39SeedGenerator(mnemonic).Generate()
bip44 = Bip44.FromSeed(seed, Bip44Coins.SOLANA)
account = bip44.Purpose().Coin().Account(0).Change(Bip44Changes.CHAIN_EXT).AddressIndex(0)
print("地址:", account.PublicKey().ToAddress())
print("私钥:", account.PrivateKey().Raw().ToHex())
Phantom / Solflare 里的第一个账号导出出来应该跟上面一样。
常见误区
Solana 地址和 ETH 地址长得像
其实完全不同:
- ETH 地址:40 字符 hex +
0x前缀,checksum 在 EIP-55 里靠大小写实现 - Solana 地址:Base58 编码的 32 字节公钥,长度 32~44 字符,无固定前缀
Solana 私钥文件是 64 字节而不是 32
Solana 的钱包 JSON(Phantom 导出)通常是 64 字节:前 32 是私钥 seed、后 32 是公钥。生成时:
priv32 = account.PrivateKey().Raw().ToBytes()
pub32 = account.PublicKey().RawUncompressed().ToBytes()[-32:]
keypair_bytes = priv32 + pub32 # 64 字节
导入 solana-cli 或 Phantom 时用这个格式。
Ed25519 派生路径可以省略部分层级
Phantom 早期用 m/44'/501'/0'(只三层)而非 m/44'/501'/0'/0'——同一助记词在这两种路径下算出来的地址不同。发现”钱包地址对不上”时先检查是不是路径差异,试试:
m/44'/501'/0'— Phantom “legacy”m/44'/501'/0'/0'— 现在的默认
一句话总结
Solana 地址生成 = BIP39 seed → SLIP-10 Ed25519 派生 → Base58(公钥)。和 EVM 完全两套加密路径,别拿 ETH 的经验类比。用 bip_utils 三行搞定,别自己实现 Ed25519。
