协议演进 / BIP/比特币改进提案 / BIP-39
BIP-39
把钱包种子编码成 12 到 24 个易记的单词:熵加校验、按 11 位查词表,再经 PBKDF2 换成可供 BIP-32 派生的 512 位种子。本 BIP 目前处于已部署状态。
一、档案卡
| 编号 | BIP-39 |
|---|---|
| 标题 | Mnemonic code for generating deterministic keys |
| 作者 | Marek Palatinus <[email protected]>, Pavol Rusnak <[email protected]>, Aaron Voisine <[email protected]>, Sean Bowe <[email protected]> |
| 指定日期 | 2013-09-10 |
| 层级 | Applications(应用) |
| 类型 | Specification(规范类) |
| 状态 | Deployed(已部署) |
| 阅读版 | https://bips.dev/39 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki |
二、放在哪一族
BIP-39 是确定性钱包族里负责“人机接口”的一环:它不定义密钥怎样派生,只定义种子怎样变成人能抄写、口述和保管的单词,以及单词怎样变回种子。
它与 BIP-32 是上下游关系:BIP-39 产出的 512 位种子,正是 BIP-32 生成主密钥的输入。再往下游是 BIP-43、BIP-44 等路径规范。
本页只讲助记词的编码与换算机制,不复述 2048 个单词的词表本身;词表在原文仓库的附属文件中。
三、它要解决什么
钱包种子本质上是一串随机数。用原始二进制或十六进制形式让人抄写、保存、口头传递,既难记又极易抄错。
原文的定位很克制:助记码是一种“搬运计算机生成的随机性”的人类可读转写方式——写在纸上,或通过电话念给对方。它明确不是把用户自己编的句子加工成种子的工具;用户自编句子(所谓脑钱包)不在本方案范围内,因为人编的句子随机性远远不够。
目标因此有二:让机器生成的高熵种子能被人可靠地搬运和保存;在抄写出错时,最好能被当场发现。
四、规则本身
4.1 从熵到助记句
助记词编码的熵(ENT)长度必须是 32 的倍数,可取 128 到 256 位;熵越长越安全,句子也越长。步骤是:
- 生成 ENT 位的初始熵;
- 取其 SHA256 哈希的前
ENT / 32位作为校验和(CS),拼在熵的末尾; - 把拼接后的比特流每 11 位切成一组,每组是一个 0 到 2047 的数,作为词表索引;
- 按索引查词表换成单词,连起来即助记句。
对应关系固定如下:
| 熵 ENT | 校验 CS | 总长 ENT+CS | 助记词数 MS |
|---|---|---|---|
| 128 | 4 | 132 | 12 |
| 160 | 5 | 165 | 15 |
| 192 | 6 | 198 | 18 |
| 224 | 7 | 231 | 21 |
| 256 | 8 | 264 | 24 |
这就是常见的“12 个词 / 24 个词”的由来:24 个词对应 256 位熵加 8 位校验。
4.2 词表的要求
理想词表有三条标准:选词要让“只打前四个字母就能唯一确定一个词”;避免形近、义近的词对(如 build 与 built、woman 与 women),它们难记又易错;词表要排序,以便二分查找与前缀树等实现手段。词表可以含本地语言字符,但必须以 UTF-8 的 NFKD 规范化形式编码。
原文同时强烈不建议在生成助记句时使用非英文词表,因为绝大多数 BIP-39 钱包只支持英文词表;确需本地化时,应使用原文列出的官方词表,而不是自创。
4.3 从助记句到种子
用户可以给助记词再加一个口令(passphrase),不用时以空字符串代替。换算用 PBKDF2:
- 密码:助记句本身(UTF-8 NFKD);
- 盐:字符串
"mnemonic"加上口令(同样 UTF-8 NFKD); - 迭代次数:2048;
- 伪随机函数:HMAC-SHA512;
- 输出:512 位(64 字节)种子。
这个种子随后可供 BIP-32 或类似方法生成确定性钱包。注意换算是单向的:原文在缺陷一节指出,无法把任意一个现成的 BIP-32 种子反向表示成 BIP-39 句子。
口令还有一个附带性质:每一个口令都会生成一个合法种子、对应一个不同的钱包,只有正确的口令才打开目标钱包——原文称这提供了可否认性(plausible deniability)。反过来说,口令忘了,助记词再完整也找不回那个钱包。
4.4 校验与实现自由度
助记句到种子的换算与助记句的生成是彼此独立的两步,代码因此很简单,客户端甚至可以自备词表或句子生成器。但原文提醒:使用非本算法生成的助记句并不被建议;软件必须用词表校验助记句的校验和,无效时要向用户报警。
4.5 原文自陈的缺陷
原文单列一节列出已知短处:种子取决于所用词表,把助记词翻译成另一种词表必然得到完全不同的种子;校验和很短,只能以不高的概率抓到随机错误(原文举例:256 分之一的错误会被漏过),也无法协助纠错;最初没有版本机制,无从从助记句本身判断该用哪种地址格式——原文说这一点现已在很大程度上由描述符钱包(BIP-380)配合种子使用而缓解。作者后来另行提出了 SLIP-0039 作为意在改进这些短处的后继方案。
五、谁必须动
普通持币人:要动的是备份习惯:抄下钱包给出的全部助记词(顺序不能乱),并单独记清自己是否设置过额外口令。助记词加口令共同决定钱包,缺一不可。
钱包开发者:要实现熵与校验的编码、词表查表与校验报警、PBKDF2 换算,并与 BIP-32 的主密钥生成衔接;还应遵循原文对非英文词表的强烈不建议。
硬件与离线备份工具:助记句的设计目标就是纸面与口头场景,实现应让用户能在不联网的环境下完成记录与恢复验证。
共识层与全节点:完全不动。助记词是纯粹的钱包本地表示法,链上不存在、也不需要知道助记词这回事。
六、现在算不算数,以及一个常见误读
状态为 Deployed。“抄 12 / 24 个词恢复钱包”已是各类钱包的默认体验,其编码规则就来自 BIP-39;它产出的种子再交给 BIP-32 派生,这条流水线至今是主流。它自陈的缺陷也应一并记住:实现与词表选错,恢复出来的会是一个空钱包,而不是报错。
常见误读:
“助记词就是把私钥翻译成单词,自己编一句好记的话也能当助记词。”
不对。原文明确说,助记句搬运的是计算机生成的随机熵,不是处理用户自创句子的工具。自编句子的人类“随机性”经不起穷举;而且单词只是熵加校验和的查表编码,脱离词表与校验规则,一句自编的话根本不在这个体系之内。
七、延伸
- 阅读版:https://bips.dev/39
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
- 相关:BIP-32 分层确定性钱包、BIP-44 多账户层级结构、BIP-380 输出脚本描述符
- 仓库总目录:https://github.com/bitcoin/bips
