BIP39 助记词生成 Solana 地址:SLIP-10 + Ed25519 全流程

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':BIP44
  • 501':Solana 的 coin type
  • 0':account
  • 0':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。