動機
鍵確立とメッセージ認証について (Diffie-Hellman 鍵共有、公開鍵暗号、事前共有鍵、エフェメラル鍵、ノンスあたり) について自分用にまとめ。
Q1. ディッフィーヘルマン鍵共有と、他の鍵交換方式はどう違うのですか?
ディッフィーヘルマン鍵共有 (Diffie–Hellman key exchange) は、共通鍵を「送る」のではなく、公開してよい値を交換して双方が手元で同じ共通鍵を「合意して生成する」方式です。盗聴者は公開値を見られますが、共通鍵を逆算するのが計算量的に難しい前提で安全性を得ます。これに対して、事前共有鍵 (Pre-Shared Key) は、通信前に同じ秘密を安全な別経路で配っておき、接続時はその秘密を元に認証や鍵導出を行います。公開鍵暗号による鍵配送 (Key Transport) は、セッション鍵を受信者の公開鍵で暗号化して送り、受信者が秘密鍵で復号して共通鍵を得る方式です。次に、それぞれの長所短所を同じ軸で比較します。
Q2. 事前共有鍵方式・鍵配送方式・ディッフィーヘルマン鍵共有を比較すると、何が本質的に違いますか?
事前共有鍵方式は計算が軽く実装が比較的簡単ですが、鍵配布とローテーションが運用のボトルネックになり、鍵漏えい時の影響範囲も大きくなりやすいです。鍵配送方式は事前に同じ秘密を配らなくてもよい一方で、公開鍵が本当に相手のものかを保証するために証明書などの仕組みが必要になりがちです。ディッフィーヘルマン鍵共有は「共通鍵の合意」に強い一方で、単体では相手認証ができないため、証明書署名や事前共有鍵などで「この公開値は相手が出したものだ」と保証する必要があります。さらに、前方秘匿性 (forward secrecy) の観点では、接続ごとに一時鍵を使うディッフィーヘルマン鍵共有が有利になりやすいです。次に、エフェメラル鍵を誰が使うかを整理します。
Q3. エフェメラル鍵 (使い捨て鍵) は、サーバーとクライアントのどちらが使うのが一般的ですか?
一般的には、両者がエフェメラル鍵ペアを生成してディッフィーヘルマン鍵共有を行います。鍵共有をエフェメラルで行うことで、過去の通信鍵が長期鍵の漏えいから守られやすくなり、前方秘匿性を得られます。一方で、認証には長期鍵を使うことが多く、たとえばサーバーが証明書の長期秘密鍵で署名し、クライアントはそれを検証して「相手が正しいサーバーである」と確認します。つまり「鍵共有は両者エフェメラル、認証は長期鍵」という分担が典型です。次に、WireGuard がどのようにこれを実現しているかを見ます。
Q4. WireGuard はディッフィーヘルマン鍵共有を使っていますか? 事前に交換する公開鍵は何のためですか?
WireGuard は楕円曲線ディッフィーヘルマン鍵共有 (Elliptic-curve Diffie–Hellman) を用いて共有秘密を作り、そこから通信鍵を導出します。設定で交換しておく Peer の公開鍵は、相手を識別し相互認証の土台となる「長期 (固定) の静的鍵ペア」の公開鍵です。ハンドシェイクでは別途エフェメラル鍵も生成して混ぜるため、静的鍵だけに依存せずに通信鍵を更新でき、前方秘匿性を得やすくなります。直感的には「静的公開鍵で誰と話すかを縛る」「エフェメラル鍵で毎回の通信鍵を作る」という分担です。次に、事前共有鍵とエフェメラル鍵共有を組み合わせたときの前方秘匿性を整理します。
Q5. 事前共有鍵で認証してから、エフェメラルなディッフィーヘルマン鍵共有で通信鍵を作ると、前方秘匿性は失われますか?
通常は失われません。前方秘匿性は「後日、長期秘密が漏れても、過去に記録された通信が復号されにくい」性質で、エフェメラルなディッフィーヘルマン鍵共有がその性質を作る代表例です。事前共有鍵を認証用途として使い、通信鍵がエフェメラルな共有秘密に依存していれば、攻撃者が後から事前共有鍵だけを入手しても過去通信の通信鍵を再現できない構造になります。逆に、通信鍵が事前共有鍵だけから導出される設計だと、事前共有鍵の漏えいが過去通信の復号に直結し、前方秘匿性が崩れます。次に、事前共有鍵による認証を強化したい場合の選択肢を整理します。
Q6. 事前共有鍵による認証で、HMAC-SHA256 より強い方式はありますか?
候補はありますが、HMAC-SHA256 は現在でも標準的で強固と見なされており、問題の多くは鍵の短さや鍵の使い回し、鍵分離不足、リプレイ対策不足に起因します。そのうえで方式として強度や設計余裕を上げたい場合は、HMAC-SHA512 (または HMAC-SHA384) や、SHA-3 系の HMAC (HMAC-SHA3-256 など) が候補になります。用途によっては KMAC (SHA-3 系のメッセージ認証コード) や、BLAKE2 の keyed モードを検討することもありますが、採用要件として標準化や監査の都合を確認すると安全です。実務上は、十分に長いランダム鍵を使い、用途ごとに鍵を分離し、リプレイ対策を入れることが強度向上に直結します。次に、リプレイ対策の中核であるノンスを具体例で理解します。
Q7. ノンスを入れるとリプレイ攻撃に強くなるのはなぜですか?
リプレイ攻撃は、攻撃者が正当な要求を盗聴して、そのまま再送して同じ効果をもう一度発生させる攻撃です。HMAC が付いていても、メッセージが同一なら認証子も同一なので、受信側が「それが初回かどうか」を判定できないと受理してしまいます。ノンスは使い捨て値で、メッセージに含め、かつ HMAC の計算対象にも含めます。サーバーは署名検証後にノンスが未使用であることを確認し、処理したらそのノンスを使用済みとして記録します。攻撃者が同じ要求を再送してもノンスが重複しているため拒否でき、これがリプレイ耐性になります。
Q8. ノンス設計にはどんな種類があり、何に気をつけるべきですか?
ランダムノンス方式では、クライアントが十分大きいランダム値を毎回生成し、サーバーは一定期間だけ使用済み集合を保持して重複を拒否します。単調増加カウンタ方式では、クライアントが 1,2,3…と番号を振り、サーバーは最後に受理した番号より大きいものだけを通します。タイムスタンプ方式は受理時間窓を狭められますが、時間窓内の再送を完全には防げないため、厳密に止めたいならタイムスタンプと一意な要求識別子を組み合わせます。どの方式でも、ノンスが署名対象に含まれていないと改ざんで回避され、サーバーが使用済みを記録しないと重複排除できません。最後に、ノンスのスコープは鍵やクライアント識別子ごとに分離し、衝突や誤拒否を避ける必要があります。次に、用途に合わせて「どの方式を採ると運用事故が減るか」を具体的に落とし込めます。