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.