协议演进 / 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 位;熵越长越安全,句子也越长。步骤是:

  1. 生成 ENT 位的初始熵;
  2. 取其 SHA256 哈希的前 ENT / 32 位作为校验和(CS),拼在熵的末尾;
  3. 把拼接后的比特流每 11 位切成一组,每组是一个 0 到 2047 的数,作为词表索引;
  4. 按索引查词表换成单词,连起来即助记句。

对应关系固定如下:

熵 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:

这个种子随后可供 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 派生,这条流水线至今是主流。它自陈的缺陷也应一并记住:实现与词表选错,恢复出来的会是一个空钱包,而不是报错。

常见误读:

“助记词就是把私钥翻译成单词,自己编一句好记的话也能当助记词。”

不对。原文明确说,助记句搬运的是计算机生成的随机熵,不是处理用户自创句子的工具。自编句子的人类“随机性”经不起穷举;而且单词只是熵加校验和的查表编码,脱离词表与校验规则,一句自编的话根本不在这个体系之内。

七、延伸

本页内容整理自 bitcoin/bips 仓库与 bips.dev,事实已与仓库核对;解读仅供学习参考。