読む前にこの記事のポイントを音声で確認できます。この音声は本記事をもとにAIツール(NotebookLM)で自動生成したもので、発音や言い回しが不自然な箇所や、内容の誤りが含まれる可能性があります。理解の補助としてご利用ください。
暗号化して通信するには、送る側と受け取る側が同じ鍵を持っている必要があります。ところが、その鍵をネットワークでそのまま送ると、途中で誰かに見られてしまいます。
この問題を解決するのが Diffie-Hellman(ディフィー・ヘルマン、以下 DH)鍵交換です。この記事では、数式を使わずに「絵の具を混ぜる」イメージで DH の仕組みを説明し、そのうえで TLS と IPsec(IKE)のどこで DH が使われているのか、DH の鍵長(DH グループ)をどう選べばよいのかを見ていきます。
- 絵の具のイメージで見る DH 鍵交換の流れ(秘密の色は送らない)
- 盗み見る第三者が鍵を作れない理由と、DH だけでは防げないこと(なりすまし)
- TLS と IPsec(IKE)で DH を使っている場所
- DH グループと鍵長の選び方(2048 ビット以上、ECDH)
なぜ鍵の受け渡しが問題になるのか
アリスとボブが、インターネット越しに暗号化した通信をしたいとします。暗号化と復号には、二人が同じ鍵(共通の鍵)を持っている必要があります。
しかし、アリスが作った鍵をそのままボブに送ると、通信を盗み見ているイブにも鍵が見えてしまいます。イブが鍵を手に入れれば、その後の暗号化された通信もすべて読めます。
DH 鍵交換は、「途中のやり取りを全部見られても、見ている人には鍵が作れない」方法で、アリスとボブに同じ鍵を持たせます。鍵そのものは一度もネットワークに流れません。
絵の具で考える DH 鍵交換
DH の仕組みは、絵の具を混ぜるイメージで説明できます。ポイントは、絵の具は「混ぜるのは簡単だが、混ざった色を元の色に分けることはできない」という性質です。赤と青を混ぜると紫になりますが、紫から赤と青を取り出すことはできません。
共通の色を決める(公開してよい)
まず、アリスとボブは共通に使う色(ここでは黄色)を決めます。この黄色は秘密ではありません。ネットワークで送るので、イブにも見えています。
自分だけの秘密の色を選ぶ
次に、アリスは自分だけの秘密の色として赤を、ボブは青を選びます。この赤と青は誰にも送りません。相手にも見せない、という点が大事です。
混ぜた色を交換する
アリスは黄色に赤を混ぜた「黄+赤」を作ってボブに送り、ボブは黄色に青を混ぜた「黄+青」を作ってアリスに送ります。この混ぜた色はネットワークを流れるので、イブにも見えます。しかし、混ざった色から元の赤や青を取り出すことはできません。
受け取った色に自分の秘密の色を混ぜる
アリスは、ボブから受け取った「黄+青」に自分の赤を混ぜます。ボブは、アリスから受け取った「黄+赤」に自分の青を混ぜます。どちらも、黄・赤・青が同じ量ずつ混ざった同じ色になります。この色が二人の共通の鍵です。
ここまでのやり取りで、誰がどの色を知っているかを整理すると次のようになります。
| 色 | アリス | ボブ | イブ(盗み見) |
|---|---|---|---|
| 黄(共通の色) | 知っている | 知っている | 知っている |
| 赤(アリスの秘密) | 知っている | 知らない | 知らない |
| 青(ボブの秘密) | 知らない | 知っている | 知らない |
| 黄+赤、黄+青(交換した色) | 知っている | 知っている | 知っている |
| 黄+赤+青(共通の鍵) | 作れる | 作れる | 作れない |
イブが鍵を作れない理由
イブが見られるのは、黄、黄+赤、黄+青の3つです。共通の鍵を作るには、黄+青に「赤だけ」を混ぜる(または黄+赤に「青だけ」を混ぜる)必要があります。ところが、イブは赤も青も持っていません。
見えた「黄+赤」と「黄+青」をそのまま混ぜても、黄色が2回分入った「黄+黄+赤+青」になり、二人の鍵とは違う色になります。混ぜた色から赤や青を取り出すこともできないので、イブには鍵が作れません。
実際の DH では、絵の具を混ぜる代わりに、ある計算を使います。この計算は、答えを出すのは簡単なのに、答えから元の秘密の値を求めるのは、現実的な時間ではできないほど難しい、という性質を持っています。これを「離散対数問題」と呼びます。楕円曲線を使った DH(ECDH)では、楕円曲線上の同じような難しさ(楕円曲線離散対数問題)を使います。
なお、RSA 暗号の安全性は「大きな数の素因数分解が難しいこと」に基づいており、DH とは根拠になっている問題が違います。公開鍵暗号やデジタル署名の全体像は 公開鍵暗号、認証局、デジタル署名をイメージで解説 で説明しています。
DH だけでは防げないこと(なりすまし)
DH は、通信を「見ているだけ」の第三者に対しては安全です。しかし、イブが通信の途中に入り込んで、やり取りを書き換えられる場合は話が違います。
イブがアリスに対してはボブのふりを、ボブに対してはアリスのふりをすると、イブはアリスと鍵 A を、ボブと鍵 B を別々に作れます。アリスから届いた通信を鍵 A で復号して中身を読み、鍵 B で暗号化し直してボブに渡せば、二人に気付かれずに通信を読めてしまいます。これを中間者攻撃(Man-in-the-Middle)と呼びます。
DH は「相手が本物かどうか」を確かめる仕組みを持っていません。そのため、実際のプロトコルでは DH に「認証」を組み合わせます。TLS ではサーバ証明書と署名、IPsec の IKE では事前共有鍵や証明書を使って、DH の相手が本物であることを確かめます。
TLS では、どこで DH を使うのか
HTTPS などで使う TLS では、通信の最初のハンドシェイクで DH を使い、その後のデータを暗号化する鍵の元を作ります。TLS 1.3 と TLS 1.2 で、DH の値を送るメッセージが違います。
TLS 1.3:ClientHello と ServerHello の key_share
TLS 1.3 では、クライアントが最初に送る ClientHello に、使える DH グループの一覧(supported_groups 拡張)と、自分の DH の値(key_share 拡張)を入れます。絵の具でいえば「黄+赤」にあたる値です。サーバは ServerHello の key_share で自分の DH の値(「黄+青」)を返します。
この時点で、クライアントとサーバは同じ鍵の元を持てるので、ServerHello より後のメッセージは暗号化されます。続く Certificate と CertificateVerify で、サーバは証明書と署名を送り、自分が本物であることを示します。これが前の章で見た「認証」にあたります。
クライアントが key_share で送った DH グループをサーバが使えない場合でも、supported_groups に共通のグループがあれば、サーバは HelloRetryRequest でそのグループを指定し、クライアントがやり直します。TLS 1.3 の鍵交換は、DH(ECDH を含む)を使うか、事前共有鍵(PSK)と組み合わせて使う形になっており、DH を使わない RSA 鍵交換はなくなりました。
TLS 1.2:ServerKeyExchange と ClientKeyExchange
TLS 1.2 では、DH を使うかどうかを暗号スイートで決めます。暗号スイート名に DHE や ECDHE が入っていれば DH を使います(例:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)。この場合、サーバは ServerKeyExchange で自分の DH の値を、証明書の鍵で署名して送り、クライアントは ClientKeyExchange で自分の DH の値を送ります。
一方、TLS_RSA_WITH_AES_128_GCM_SHA256 のような RSA 鍵交換の暗号スイートでは DH を使いません。クライアントが作った鍵の元を、サーバの公開鍵で暗号化して送ります。
DHE と ECDHE の「E」は Ephemeral(一時的な)の意味で、通信のたびに新しい秘密の値(絵の具でいえば赤と青)を選び、使い終わったら捨てます。そのため、後からサーバの秘密鍵が漏れても、過去に記録された通信の鍵は作れません。この性質を前方秘匿性(Perfect Forward Secrecy、PFS)と呼びます。
RSA 鍵交換では、サーバの秘密鍵が漏れると、記録しておいた過去の通信から鍵の元を取り出せてしまいます。TLS 1.3 で RSA 鍵交換がなくなったのは、このためです。
Wireshark で TLS のハンドシェイクを見る場合は、TLS 1.3 なら ClientHello と ServerHello の key_share 拡張の中にある Group(例:x25519)を、TLS 1.2 なら ServerKeyExchange の中の DH のパラメータを確認すると、どの DH グループが使われたかがわかります。
IPsec(IKE)では、どこで DH を使うのか
IPsec VPN では、通信を暗号化する前に IKE(Internet Key Exchange)で鍵や暗号方式を取り決めます。この IKE の中で DH を使います。
IKEv2:IKE_SA_INIT の KE ペイロード
IKEv2 では、最初のやり取りである IKE_SA_INIT で、暗号方式の提案(SA ペイロード。DH グループもここに含まれます)、DH の値(KE ペイロード)、乱数(Nonce)を送り合います。双方は DH で作った値と Nonce から鍵の元(SKEYSEED)を作り、そこから IKE で使う暗号化と認証の鍵を作ります。
続く IKE_AUTH は、この鍵で暗号化されます。IKE_AUTH では事前共有鍵や証明書を使ってお互いを認証し、同時に最初の IPsec SA(Child SA)を作ります。最初の IPsec SA の鍵は、IKE_SA_INIT の DH で作った鍵の元から作るので、ここでは改めて DH をしません。
IPsec SA を作り直すとき(リキー)や、追加の IPsec SA を作るときは CREATE_CHILD_SA を使います。このとき KE ペイロードを入れて新しく DH をすると、IPsec SA の鍵が IKE SA の鍵とは独立し、前方秘匿性が強くなります。機器の設定で「PFS」や「PFS グループ」と呼ばれているのが、この追加の DH です。
IKEv1:メインモードとクイックモード
IKEv1 のメインモードでは、6つのメッセージでやり取りします。1〜2番目で暗号方式(DH グループを含む)を決め、3〜4番目で DH の値(KE)と Nonce を送り合い、5〜6番目で暗号化された状態でお互いを認証します。続くクイックモードで IPsec SA を作るときに、PFS を有効にしていれば、ここでも追加の DH をします。メインモードの流れは 【IPSec】IKE(メインモード) で詳しく説明しています。
IKE では、両側の機器で同じ DH グループを使えるように設定しておく必要があります。共通のグループがないと、ネゴシエーションが失敗して VPN がつながりません。PFS を使う場合は、PFS グループも両側でそろえます。
TLS と IKE で DH を使う場所をまとめると、次のようになります。
| プロトコル | DH の値を送る場所 | 相手の認証 |
|---|---|---|
| TLS 1.3 | ClientHello/ServerHello の key_share | Certificate と CertificateVerify(証明書と署名) |
| TLS 1.2(DHE/ECDHE) | ServerKeyExchange(署名付き)/ClientKeyExchange | サーバ証明書と ServerKeyExchange の署名 |
| IKEv2 | IKE_SA_INIT の KE ペイロード(PFS は CREATE_CHILD_SA の KE) | IKE_AUTH(事前共有鍵や証明書) |
| IKEv1 | メインモードの3〜4番目のメッセージ(PFS はクイックモード) | メインモードの5〜6番目のメッセージ |
鍵長(DH グループ)の選び方
DH の安全性は、使う数の大きさ(鍵長)で決まります。IKE では、DH の種類と鍵長の組み合わせに「DH グループ」という番号が付いていて、機器の設定ではこの番号を選びます。TLS 1.3 では x25519 や ffdhe2048 のような名前で指定します。
| IKE の DH グループ | 種類と鍵長 | RFC 8247 での扱い(IKEv2) |
|---|---|---|
| グループ 1 | DH(MODP)768 ビット | 使ってはいけない(MUST NOT) |
| グループ 2 | DH(MODP)1024 ビット | 使うべきではない(SHOULD NOT) |
| グループ 5 | DH(MODP)1536 ビット | 使うべきではない(SHOULD NOT) |
| グループ 14 | DH(MODP)2048 ビット | 実装しなければならない(MUST) |
| グループ 15/16 | DH(MODP)3072/4096 ビット | 表には記載なし |
| グループ 19 | ECDH 256 ビット | 実装すべき(SHOULD) |
| グループ 20/21 | ECDH 384/521 ビット | 表には記載なし |
| グループ 31 | Curve25519(ECDH) | 表には記載なし |
RFC 8247 は IKEv2 で使う暗号アルゴリズムの要件をまとめた文書です。グループ 1 は数時間で破られうること、グループ 2 は資金力のある攻撃者には弱いこと、グループ 5 も国家レベルの攻撃者には数年以内に破られうることを理由に、これらを使わない方向にしています。「表には記載なし」のグループは、使ってはいけないという意味ではなく、RFC 8247 が要件を定めていないという意味です。
ECDH は短い鍵長で同じ強さになる
楕円曲線を使う ECDH は、通常の DH よりずっと短い鍵長で同じ強さになります。NIST(米国国立標準技術研究所)の SP 800-57 では、強さの目安を次のように対応付けています。
| 強さの目安 | DH(MODP) | ECDH | 共通鍵暗号の目安 |
|---|---|---|---|
| 80 ビット | 1024 ビット | 160 ビット | ―(現在は使わない強さ) |
| 112 ビット | 2048 ビット | 224 ビット | 3DES(3 鍵) |
| 128 ビット | 3072 ビット | 256 ビット | AES-128 |
| 192 ビット | 7680 ビット | 384 ビット | AES-192 |
| 256 ビット | 15360 ビット | 512 ビット以上 | AES-256 |
たとえば、DH の 2048 ビット(グループ 14)は 112 ビット相当、ECDH の 256 ビット(グループ 19)は 3072 ビットの DH と同じ 128 ビット相当です。ECDH は鍵長が短い分、計算も軽く済みます。
2015 年に公表された Logjam という攻撃では、TLS で 512 ビットの弱い DH を使うように通信を格下げ(ダウングレード)させる手口と、多くのサーバが同じ 1024 ビットの値を共有していることが示されました。公表した研究者は、国家レベルの攻撃者なら 1024 ビットの DH は破れると見積もり、2048 ビット以上の DH グループか ECDHE を使うよう勧めています。
どれを選べばよいか
- DH(MODP)を使うなら、少なくともグループ 14(2048 ビット)にします。グループ 1、2、5 は使いません。
- 機器が対応していれば、ECDH(グループ 19、20、31 など)を選ぶと、短い鍵長で強さを確保でき、処理も軽くなります。
- 128 ビット相当の強さが必要な場合は、DH なら 3072 ビット以上(グループ 15 以上)、ECDH なら 256 ビット以上にします。NIST では、最低限の強さを 2030 年末に 112 ビットから 128 ビットへ引き上げる案が示されています(案の段階です)。
- IKE では両側の機器で同じグループを選べるようにし、PFS グループも同じ考え方で選びます。
大規模な量子コンピュータが実用化されると、DH も ECDH も鍵長に関係なく破られると考えられています。そのため、従来の ECDH に量子コンピュータでも破られにくいとされる ML-KEM を組み合わせた「ハイブリッド鍵交換」が TLS で使われ始めています。IKEv2 でも、複数の鍵交換を組み合わせる仕組みが RFC 9370 で定められています。
まとめ
| 項目 | ポイント |
|---|---|
| DH の考え方 | 共通の色(公開)に自分だけの秘密の色を混ぜて交換し、受け取った色に自分の秘密の色を混ぜると、二人だけが同じ色(鍵)を作れる |
| 盗み見に強い理由 | 秘密の色は送らない。混ぜた色から元の色は取り出せず、交換した色同士を混ぜても鍵にはならない |
| DH の弱点 | 相手が本物かは確かめられない。なりすましを防ぐには、証明書や事前共有鍵による認証を組み合わせる |
| TLS | TLS 1.3 は ClientHello/ServerHello の key_share。TLS 1.2 は DHE/ECDHE のときに ServerKeyExchange/ClientKeyExchange |
| IPsec(IKE) | IKEv2 は IKE_SA_INIT の KE ペイロード、IKEv1 はメインモードの3〜4番目。PFS を使うと IPsec SA を作るときにも追加の DH をする |
| 鍵長 | DH は 2048 ビット(グループ 14)以上。ECDH(グループ 19、20、31 など)は短い鍵長で同等以上の強さ |
コメント