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 ではこのブロック一つで足ります。単にテキストに SHA-512 を 2048 回適用するだけでは、計算も結果も別のものになります。 [2] [1]
別のウォレットで復元する場面を考えてみてください。同じ seed を得るには、正規化後のデータも設定も同じでなければなりません。規定の 2048 回より反復を増やしても、復元の改善にはなりません。BIP39 から外れ、異なる結果になるからです。単語を別の単語リストの言語へ翻訳することも、結果に影響しない変更ではありません。復元に必要なのは一致であり、独自のアルゴリズム改変ではないのです。 [1]
計算の反復は一回の試行にかかる負担を増やしますが、新たな独立したランダム性は作りません。攻撃者がバックアップ単語を知り、正しいウォレットを見分ける情報も持っていれば、弱い passphrase を自分のコンピューターでオフライン試行できます。したがって、seed が 512 ビット長でも、予測困難さが 512 ビットあるとは限りません。また、2048 という数は新規システム全般への推奨値ではなく、ここでは特定の復元規格の一部です。 [2] [1]
BIP39 のチェックサムは、単語の書き写し間違いを見つける助けになります。PBKDF2 が扱うのは、与えられた入力からどう seed を計算するかという別の問題です。この計算だけでは、passphrase が元のウォレットに対応しているとは確認できません。その後は、例えば BIP32 が seed を処理し、一連の鍵を導出します。記録の確認、seed への変換、鍵の生成はつながっていますが、互いの代わりにはなりません。 [1]
開発者は公開テストベクトル、つまり既知の入力と期待される出力を使って結果を比較できます。BIP39 は元のランダムデータ、単語列、そしてテスト用 passphrase TREZOR に対する seed 全体を公開しています。正しい実装は NFKD の規則も含めて結果を再現できなければなりません。テストに本物のバックアップは不要です。逆に、誰でも知っている公開例を資金の保管に使ってはいけません。計算テストに合格しても、アプリ全体の安全性が証明されるわけではありません。 [1]
理解を深めるには、この項目とあわせて次もお読みください BIP 39, BIP39 passphrase, Seed Generation, HD Wallet. 次の項目からも参照されています BIP39 passphrase.