VPNにおける共通鍵暗号と公開鍵暗号:それぞれの役割
VPNは公開鍵で相手を認証し、そこから導出したセッション鍵でパケットを暗号化します。証明書と通信鍵を別のオブジェクトとして扱ってください。
人々はVPNを「公開鍵暗号を使うもの」と説明し、そのうえで各パケットがサーバーの証明書で施錠されていると想像します。このイメージは、設定ファイルやパケットキャプチャを読むときに重要になる形で誤っています。VPNの公開鍵側は相手が誰かを証明し秘密の素材に合意するためのもので、共通鍵側がセッションの寿命のあいだパケットごとに通信を実際に守ります。
二つの半分は寿命も故障の仕方も安全に公開できるものも異なります。切り離してしまえば、「RSA 2048はAES-128より弱いのか」といった疑問は、そもそも比較可能ではなかったため、混乱を招かなくなります。
まとめて語られがちな三つの操作
公開鍵暗号は少なくとも三つの異なる操作をまとめた傘です。署名は、秘密鍵の持ち主が特定のメッセージを承認したことを証明します。鍵合意は、二つの相手が公開で交換した値から共有の秘密を導出できるようにします。公開鍵暗号は、ある人の公開鍵の下にデータを隠し、その秘密鍵だけが開けるようにします。
VPNのハンドシェイクは主に最初の二つを使います。証明書は暗号鍵ではなく、名前を公開鍵に結び付ける署名済みの表明であり、受け取ったばかりの鍵を信頼するかどうかを相手側が決められるようにします。たとえばTLS 1.3の鍵確立は、(EC)DHEの鍵合意と証明書の署名に基づいており、サーバーの公開鍵でセッションを暗号化するものではありません。
ハンドシェイクが実際に生み出すもの
現代のハンドシェイクでは、双方が一時的な鍵ペアを生成し、公開側の半分を交換して、決して回線を渡らない共有の秘密を計算します。その秘密は鍵導出関数に通され、方向ごとに別々の鍵と、レコード層が必要とするnonceおよびIVの素材が作られます。WireGuardはNoiseに基づく構成でこれを行い、TLS 1.3はハンドシェイクのトランスクリプトに対するHKDFで行います。
長期的な資格情報、つまり証明書と秘密鍵、または静的なWireGuard鍵は、その交換を認証します。トランスクリプトに署名するか混ぜ込むことで、第三者が相手の代わりにハンドシェイクを完了できないようにします。その後、資格情報がパケットごとの仕事をすることはありません。もしそうなら、各パケットに秘密鍵演算が必要になり、多忙なトンネルはスタック内で最も遅い演算に制限されるでしょう。
副作用は二つあります。第一に、セッション鍵は毎回新しくなるため、後から長期鍵を盗んだ攻撃者でも、合意が一時的であったなら、以前に記録したセッションを復号できません。第二に、漏えいしたセッション鍵が危険にさらすのは一つのセッションであり、身元ではありません。
大量データが共通鍵を使う理由
共通鍵暗号は量をうまく扱います。AES-GCMやChaCha20-Poly1305は、すでにメモリにある鍵で各パケットを処理し、ヘッダーを認証し、カウンターを進めます。受信側はnonceと認証タグを確認し、失敗したものや再生されたものを捨てます。通常のハードウェアで回線速度で動かせるほど安価であり、同じ構成が一回の処理で機密性と完全性を与えます。
この構成は、実装上のバグの大半が住む場所でもあります。GCMでnonceが繰り返されると機密性と真正性が同時に破れるため、プロトコルは方向ごとに鍵を導出し、明示的なカウンターまたはエポックを維持します。パケットキャプチャを読み、暗号文の長さが平文に固定のオーバーヘッドを加えたものと一致するなら、働いているのは共通鍵層であり、パケットごとの公開鍵演算ではありません。
寿命、鍵の更新、前方秘匿性
セッション鍵は失効するものです。TLS 1.3はKeyUpdateメッセージで通信鍵を更新でき、WireGuardは設定した時間またはメッセージ数でセッションを更新し、途中のパケットのために古い鍵をしばらく保持します。OpenVPNはスケジュールに従ってデータチャネルの鍵を再交渉し、reneg-secが間隔を制御します。
これらの更新はどれも証明書の更新とは同じではありません。証明書は一年有効なままセッション鍵は数分ごとに変わることもあり、稼働中のトンネルの鍵に触れずに証明書を差し替えることもできます。失効を計画するときは、どのオブジェクトを更新しているのかを問いかけてください。その答えが、クライアントが再接続するのか鍵を更新するだけなのかを決めます。
オブジェクトを混同せず設定と診断を読む
実際には、完全なプロトコルとその対応プリミティブを選ぶのであって、自分で組み立てるのではありません。OpenVPNの--tls-crypt鍵は制御チャネルを保護し、データチャネルは交渉された共通鍵暗号を使います。WireGuardのPrivateKeyとPublicKeyの項目は身元の素材であり、その転送鍵は内部で導出されます。これらのフィールドを同じ種類の秘密として読むと、秘密鍵のあるべき場所に公開鍵を貼るといった誤りにつながります。
公開の素材を秘密の素材から切り離しておく。証明書、WireGuardの公開鍵、指紋はチケットで共有しても安全です。秘密鍵、事前共有鍵、エクスポートしたセッション鍵は安全ではありません。強度を比べるときは同じ型の範囲で比べてください。楕円曲線の識別子、RSAの法の大きさ、AES鍵の大きさはそれぞれ異なる前提の下で異なるものを測っています。TLS 1.3の仕様は、トンネルがTLSでなくても、二つの層がどうかみ合うかを知るための有用な参照です。