要約

  • HKDFのsaltは通常、秘密ではない。それでも抽出の独立性を強められるが、入力にないエントロピーを増やしたり、パスワードの総当たりを遅くしたりはできない。
  • 展開段階の info は、鍵をプロトコル、版、役割、用途へ結び付ける別の入力である。導出結果を証拠にするには、IKM、salt、符号化済み文脈、出力の保管責任を分けて残す必要がある。

同じ32バイトでも、同じ鍵ではない

暗号ライブラリが32バイトを返し、通信の両端で値が一致した。試験項目だけを見れば成功である。しかし、その値が送信用鍵なのか、受信用鍵なのか、IVなのか、別プロトコルのexporterなのかを入力に含めていなければ、「正しく一致した」という事実は用途を保証しない。

鍵導出を単なるハッシュ処理と考えると、この欠落が見えなくなる。必要なのは、偏りのあり得る元データから扱いやすい中間秘密を得る工程と、その秘密から用途ごとに異なる出力を得る工程を分けることだ。Hugo Krawczykが論文で分析し、Pasi EronenとRFC 5869にまとめたHKDFは、この二段階をExtractとExpandとして固定した。

人物の実績を過大に語る必要はない。IETFの記録では、KrawczykはHMACのRFCとHKDFのRFCの著者の一人である。2025年のACM賞資料も、安全な通信の理論と実用プロトコルを結んだ功績を評価している。この経歴が本稿に関係するのは、ひとつの設計思想がTLS、QUIC、HPKE、MLSへ渡っていったからである。中間値と最終用途を分ける発想は、今やインターネット運用の一部だ。

Extractが増やせるもの、増やせないもの

HKDF-Extractは次の形を取る。

PRK = HMAC-Hash(salt, IKM)

IKMは入力鍵材料、PRKは固定長の擬似乱数鍵である。IKMの分布が一様でなくても、そこに十分な不確実性があれば、Extractはそれを後段で扱いやすい形へ集中させる。だが、候補が千個しかない入力を百万通りに増やす装置ではない。攻撃者がIKM候補を列挙できれば、同じHMACを高速に繰り返せる。

Extractを省けるかどうかも入力次第である。IKMがすでに良質な擬似乱数鍵なら、Expandだけを使える場合がある。一方、Diffie–Hellman共有値をそのまま一様なHMAC鍵と見なすべきではなく、RFC 5869はこの場合にExtractを省かないよう求める。NIST SP 800-56C Rev. 2も、鍵確立の方法を抽出、展開、抽出後の展開として整理している。ここでの段階は性能上の飾りではなく、入力について置いた仮定を記録する境界である。

見えていても働くsalt

RFC 5869のsaltは非秘密の値であり、省略時にはハッシュ出力長のゼロ列が使われる。公開ノンスから作ることも、適切な固定値を再利用することもあり得る。したがって、saltがパケットや設定に見えたというだけで、秘密漏えいとは言えない。

それでもsaltには意味がある。ハッシュ関数の異なる利用を独立させ、入力源に依存しにくい抽出を支え、設計の解析条件を強めるからだ。効果はsaltを隠すことではなく、IKMとの関係を正しく設計することから生じる。

ただし、公開と攻撃者任せは同義ではない。saltはIKMから独立している必要があり、当事者のノンスを使うなら、攻撃者が都合のよい値を選べないよう認証が要る。監査で見るべきは「salt有り」という一項目ではない。プロトコル既定値か、固定値か、新鮮で認証済みの公開値か、外部から操作可能な値かを区別しなければならない。

HTTP暗号化コンテンツ符号化を定めるRFC 8188は好例である。通信で運ばれるsaltをExtractへ入れ、コンテンツ符号化を示す固定文字列をExpandの info に入れる。どちらも読めるが、前者は抽出、後者は用途の指定に使われる。公開性ではなく、計算のどこに何の根拠で入るかが違う。

パスワード用saltとの取り違え

パスワード保存にもsaltが登場するため、「saltがあれば強化済み」という省略が起きやすい。パスワード用の一意なsaltは、事前計算を使い回しにくくし、同じパスワードの出力を分ける。しかし人間が選ぶ文字列の候補空間は狭い。オフライン攻撃への対抗には、一回の推測に意図的な時間またはメモリ費用を課す必要がある。

HKDFには反復回数もメモリ困難工程もない。RFC 5869自身が、Extractは既存のエントロピーを集中できても増幅できず、パスワードKDFの減速機構を持たないと説明している。PBKDF2は反復回数を引数にし、Argon2はメモリ量、繰り返し、並列度を設計に含める。弱いパスワードを強い秘密へ変える魔法ではないが、推測の単価を上げる制御である。

ゆえに「saltを使ったか」という質問だけでは足りない。どの関数がsaltを消費したか、元データは高エントロピーの鍵か人間のパスワードか、一回の推測費用はいくらか、saltには独立性と一意性のどちらが必要かを確かめるべきだ。

info は用途を計算に入れる

HKDF-ExpandはPRK、info、出力長から鍵材料を作る。info にはプロトコル番号、アルゴリズム、利用者の識別情報、長さなどを入れられる。目的は、同じIKMから別の文脈で同じ意味のない材料が出ないよう、用途そのものを導出へ結び付けることだ。

この役割をsaltへ移すことはできない。RFC 5869は、短い出力であってもPRKをそのまま最終鍵にすることを勧めていない。info を通らないからである。また文脈情報をExtractへ押し込む代用も推奨しない。PRKは「後で用途を割り当てる中間秘密」であり、完成した業務権限ではない。

TLS 1.3では HKDF-Expand-Label が tls13 という接頭辞、用途ラベル、文脈を符号化し、握手トランスクリプトも鍵日程に入る。QUICはさらに quic key、quic iv、quic hp を使い、AEAD鍵、IV、ヘッダー保護鍵を分ける。RFC 9001は、これがQUICとTLSの鍵分離にもなると明記する。

HPKEのLabeledExtract/LabeledExpandは HPKE-v1、暗号スイート識別子、用途ラベルを含める。MLSも MLS 1.0 接頭辞を使い、epoch内の複数の秘密を別々に派生する。人間に読みやすい名前を付けただけではない。全実装が同じ曖昧さのないバイト列を作り、版とスイートを検証して初めて、ラベルは暗号学的な境界になる。

監査で残す四つの記録

第一はIKMの由来である。認証済み鍵交換、乱数鍵、事前共有秘密、パスワード、別のKDF出力を同じ「secret」型に押し込まない。長さが同じでも、エントロピーと攻撃者の関与は異なる。

第二はsaltの由来である。実バイトを公開ログへ出す必要はなくても、生成規則、版、認証状態、再利用方針、IKMから独立と判断した根拠は残す。非秘密という属性は、正しい出所を意味しない。

第三は符号化済み文脈である。画面上のラベルではなく、Expandへ渡したプロトコル接頭辞、版、スイート、送受信役、トランスクリプトハッシュ、長さの符号化を非秘密の指紋として記録する。

第四は出力の保管責任である。鍵、IV、exporter、再開秘密、PRKのどれか、許可された操作、epoch、削除時点を示す。導出が正しくても、IVの再利用や旧鍵の残存は別の失敗になる。

この四つがそろって初めて、導出の一致を適切な範囲で解釈できる。一致は計算の再現性を示すが、相手の認証、入力の予測困難性、用途の妥当性、秘密の消去までは証明しない。

情報源