489 / 736PBKDF2

PBKDF2

BIP39 中的 seed 派生

恢复钱包时,同一组备份词加上同一个 passphrase,应当得到相同的密钥。BIP39 中,PBKDF2 负责其中一步:计算出 seed,也就是后续派生所用的秘密基础。它会重复运算,但不会凭空创造一个新的秘密。

PBKDF2 的全称是 Password-Based Key Derivation Function 2。它把密码输入和名为 salt 的附加参数转换成派生密钥。结果还取决于重复次数、所用的计算函数和要求的输出长度。输入和设置都相同,结果就相同。BIP39 采用的是 PBKDF2-HMAC-SHA512 这一具体变体;其他用途可以采用不同参数。

恢复词构成名为 password 的输入。Salt 是另一个输入:字面文本 "mnemonic" 后面直接接上 passphrase,即可选的额外密码。两者之间不加分隔符,也不再加入一遍备份词。没有 passphrase 时,salt 仍是 "mnemonic",并不是空字符串。两个输入都要经过 NFKD 处理,统一某些字符的表示方式,再用 UTF-8 编码。BIP39 使用 HMAC-SHA512,重复 2048 次,输出 64 字节,即 512 位。这个结果就是 seed;salt 并不是需要另外制作的一份备份。 [1]

内部使用的是 HMAC,它将一个密钥和一条消息结合起来计算。每一轮都使用同一个密码输入作为密钥。第一个中间结果使用 salt 和输出块编号,后续轮次则处理上一个中间结果。各次结果通过 XOR 合并,也就是对相应位置的位做异或运算。HMAC-SHA512 返回 64 字节,所以 BIP39 只需要一个这样的块。仅对文本重复执行 2048 次 SHA-512 是另一种计算,结果也不同。 [2] [1]

设想你要在另一个钱包中恢复资金。要得到相同的 seed,它必须使用相同的规范化数据和设置。增加规定的 2048 次重复并不是改进恢复过程:这会偏离 BIP39,得到另一个结果。把备份词翻译成另一份词表里的词也不是无影响的替换。恢复需要一致性,而不是自行修改算法。 [1]

重复计算会增加每次尝试的成本,却不会产生新的独立随机性。攻击者如果知道你的备份词,并掌握识别正确钱包所需的信息,就能在自己的计算机上离线尝试薄弱的 passphrase。因此,512 位长的 seed 并不意味着有 512 位的不可预测性。2048 也不是对新系统的通用建议;这里它属于某个具体的恢复标准。 [2] [1]

BIP39 的校验和有助于发现抄错的词。PBKDF2 回答的是另一个问题:怎样根据给定输入计算 seed?这个计算本身并不能确认 passphrase 对应的是你原来的钱包。随后,seed 可以交给 BIP32 处理,用来派生一整套密钥。检查记录、转换成 seed 和生成密钥彼此衔接,但不能互相替代。 [1]

开发者可以把结果与公开测试向量比较,也就是比较已知输入所对应的预期输出。BIP39 公布了原始随机数据、恢复词,以及使用测试 passphrase TREZOR 得到的完整 seed。正确实现必须遵守 NFKD 等规则,并复现结果。测试不需要你的真实备份。反过来,也绝不能用公开示例存放资金,因为任何人都知道这些数据。计算测试通过,同样不代表整个应用都安全。 [1]

要获得更完整的理解,请将本词条与以下词条结合阅读: BIP 39, BIP39 passphrase, Seed Generation, HD Wallet. 反向关联还来自: BIP39 passphrase.

DOC · 001BIP39 — Mnemonic generation and seed conversion规范 DOC · 002RFC8018 — PBKDF2 construction规范
修订日期: 来源优先 · 非投资建议