DH・ECDHEによる鍵交換とPerfect Forward Secrecy
社員端末からAPP-1のHTTPSへ接続する場面で、TLS 1.3のECDHE鍵交換を追います。サーバ証明書の秘密鍵が後日漏えいしたとき、過去の通信は読めるのでしょうか。DH、ECDHE、共有秘密、鍵導出、Perfect Forward Secrecy(PFS)を、実際のハンドシェイク順に説明します。以下の構成、時刻、ログは教材用の架空例です。
読む順序は、鍵の区別→TLS 1.3の流れ→PFSが守る範囲→例外とログ→対処→演習です。『ECDHEを使った』と『相手を認証した』も別です。科目B(午後)では、どの鍵がいつ秘密になり、攻撃者がいつ何を得たかまで条件に入れます。
1. DH・ECDHE・PFSを鍵の寿命で区別する
用語 | 意味とこの接続での役割 |
|---|---|
DH(Diffie-Hellman) | 二者が公開できる値を交換し、秘密の値を直接送らずに共有秘密を計算する鍵合意の原理。DHだけでは相手が正規のAPP-1か証明できない。 |
ECDH | 楕円曲線を使うDH。ECDHEのEはephemeral(一時的)で、接続ごとに新しい秘密値を用意する運用を指す。楕円曲線の公開値をそのまま暗号鍵として使うわけではない。 |
ECDHE | 接続ごとに新しいECDH鍵ペアを作り、共有秘密を求める方式。TLS 1.3の鍵共有グループの例にX25519やsecp256r1がある。秘密値を接続後も保存すれば期待する保護が崩れ得る。 |
共有秘密 | クライアント秘密値とサーバ公開値、または逆の組から両者が同じ値を計算する。通信路にはその値を直接流さない。TLSはこれをHKDFの鍵スケジュールに入力する。 |
PFS(前方秘匿性) | 後で長期認証鍵が漏れても、保存済みの過去の暗号化通信を、その鍵だけでは復号できない性質。過去の通信が端末上で既に平文として盗まれた場合まで救う意味ではない。 |
証明書の秘密鍵 | サーバがAPP-1であることを証明する長期認証鍵。TLS 1.3で通常の1-RTT通信鍵を直接暗号化する鍵ではない。漏えいすれば将来のなりすましリスクは残る。 |
この例では端末が`https://app.example`へ接続し、APP-1は証明書と対応する署名鍵を持ちます。端末は信頼するCA、名前、有効期間などを検証します。攻撃者は途中のパケットを記録できますが、最初は秘密鍵を持ちません。後日、APP-1の証明書秘密鍵だけが漏えいした場合を考えます。
主要メッセージだけを示す。実際の鍵スケジュールは本文で区別する。
図の`key_share`は秘密値ではなく公開値です。証明書とCertificateVerifyの署名でサーバの認証を確かめ、Finishedでハンドシェイク全体が一致したことを確認します。これらが失敗した接続ではHTTP要求を送らない設計です。
2. 共有秘密から通信鍵ができるまで
端末は一時秘密値cと公開値C、APP-1は一時秘密値sと公開値Sを作る。両者は公開値だけをClientHelloとServerHelloで交換する。
端末はcとSから、APP-1はsとCから同じECDHE共有秘密Zを計算する。盗聴者はCとSを見ても、適切なグループと実装ではZを計算できない。
TLS 1.3はZをHKDFの鍵スケジュールへ入れ、ハンドシェイク用とアプリケーション用の秘密・鍵を段階的に導く。ZをそのままAES鍵として使う説明は不正確。
サーバは証明書と署名で一時鍵交換を認証し、双方がFinishedを検証する。1-RTTのアプリケーション通信は導出された方向別の鍵で保護する。
接続の終了後は不要な一時秘密値と通信鍵を安全に破棄する。端末やサーバで鍵ログ・メモリダンプを残した場合、PFSの前提が変わる。
値 | 公開できるか/漏えいした場合 |
|---|---|
ClientHello.key_share / ServerHello.key_share | 公開値なので通信路で見える。これだけでは共有秘密を計算できない設計。 |
クライアントとサーバの一時秘密値 | 接続中は秘密。対応する一時秘密値が保存・漏えいすると、その接続の鍵導出に影響する。 |
サーバ証明書と長期秘密鍵 | 証明書は公開、秘密鍵は厳重に保管。後日の長期秘密鍵漏えいだけでは、ECDHEの過去の共有秘密を求められない。 |
HKDF出力と通信鍵 | 方向・段階ごとに導出する秘密値。鍵ログやメモリから流出すれば、その対象通信の復号につながる。 |
セッション再開用PSK / ticket | 再接続を速くする鍵材料。どの再開モードかでPFSの評価が変わる。チケット鍵・PSKの漏えい範囲を別に調べる。 |
次は架空の概念ログです。実際のTLSログの項目名や出力有無は実装次第です。`certificate_verify=ok`は署名検証の結果だけでなく、証明書チェーンやホスト名の検証結果も別途確認する必要があります。
11:00:00 tls_conn=C-41 server=app.example
version=TLS1.3 group=x25519 mode=ecdhe
certificate_chain=ok hostname=ok
certificate_verify=ok finished=ok
early_data=off action=app_data
11:00:01 http_conn=C-41 path=/reports status=200`group=x25519`と`mode=ecdhe`はこの架空ログにおける構成事実です。`status=200`はHTTP応答が成立したことを示しますが、利用者の権限やレポートの内容が正当かは別のアプリログで確認します。TLSが守るのは通信路であり、端末上やAPP-1内の平文を暗号化するわけではありません。
3. PFSが成立する条件と成立しない例
後から攻撃者が得たもの | 録画済み通信への影響 |
|---|---|
証明書の長期秘密鍵だけ | ECDHEを使い、一時秘密が破棄され、通信鍵・PSKが漏れていなければ、過去の1-RTT通信をその鍵だけで復号できない。将来のなりすまし対策は必要。 |
対象接続の一時秘密値 | 対応する公開値とハンドシェイクを記録していれば、対象接続の共有秘密や鍵導出へ影響し得る。PFSの前提である一時秘密の保護が破れている。 |
SSLKEYLOGFILE等の通信鍵 | 対象接続を復号できる可能性がある。『ECDHEだったから無害』とは言えない。試験用の鍵ログを本番に残さない。 |
0-RTTに使ったPSK | TLS 1.3の0-RTT早期データはPFSを持たず、接続間の再生防止も保証されない。後続の1-RTTと分けて評価する。 |
端末の平文・サーバのデータ | 通信鍵を解かなくても平文を得られる。PFSは侵害済み端末・サーバの保護策ではない。 |
TLS 1.3は再開時にPSKを使えます。PSKだけの鍵交換と、PSKに新しい(EC)DHEを加える方式は区別します。特に0-RTTはPSKに依存し、PFSと接続間リプレイ耐性が弱いので、状態変更を伴う操作を安易に載せない設計にします。『TLS 1.3なら全てのバイトがPFS』は誤りです。
4. 攻撃条件・失敗ログ・追加証拠
異常 | 観測と対応 |
|---|---|
中間者が公開値を差し替える | ECDHE単体では相手を認証しない。証明書・名前・CertificateVerify・Finishedの検証に失敗すれば接続を止める。検証無効化は攻撃成立条件を与える。 |
証明書名が違う | `hostname=fail`なら`app.example`へ接続したつもりの端末は先へ進めない。CA検証だけ通っても名前が違えば正規APP-1の証明にならない。 |
HelloRetryRequestがある | 提示したグループが合わない場合に再提示が起き得る。再送自体を攻撃と即断せず、選択されたグループと最終検証を確認する。 |
0-RTTを受理した | リプレイの影響を受ける操作か、受理側の保護策、再送時の重複実行を確認する。早期データの記録と1-RTTデータを混同しない。 |
サーバ秘密鍵が漏れた | 失効・差替えを行い、なりすまし期間を調べる。過去通信の秘匿性評価には鍵交換方式と一時鍵・鍵ログ・PSKの保存状況が必要。 |
攻撃者が証明書秘密鍵を先に盗み、接続時に正規サーバになりすませるなら、新しい接続は危険です。PFSが守るのは『後から長期鍵だけが漏えいした過去通信』です。時点を入れ替えると答えが変わります。また、証明書検証を無効化したクライアントには、公開鍵交換が正しく動いても中間者攻撃が成立し得ます。
5. 設定変更・障害・復旧
APP-1のサーバ証明書更新時には、秘密鍵の保管と登録、証明書チェーン、名前、期限、対応する署名方式、クライアントの検証結果を確認する。
TLS 1.2を併用する場合、古いRSA鍵交換方式とECDHE方式を混同しない。実際に合意した暗号スイートとハンドシェイクを記録し、非推奨構成への意図しないフォールバックを検出する。
鍵ログ、パケットキャプチャ、メモリダンプは調査に役立つが秘密情報を含み得る。取得・保存・削除期限とアクセス権を定める。
0-RTTを使うなら、再生されても安全な操作だけを許すか無効化する。アプリ側の冪等性と重複排除をTLS設定とは別に確認する。
漏えい後の復旧では、新しい長期秘密鍵と証明書を配布し、旧鍵を失効・停止し、正規クライアントが検証できることを試験します。過去通信を評価する際は、対象接続の鍵交換、0-RTT有無、チケットと鍵ログの扱いを調べます。鍵を更新しただけで既に盗まれた平文を回収できるわけではありません。
5-1. 小さなDH計算で共有秘密を確かめる
仕組みだけを理解するため、危険なほど小さい素数p=23と生成元g=5を仮定します。端末の秘密値c=6なら公開値C=5の6乗を23で割った余りの8、サーバの秘密値s=15なら公開値S=19です。端末は19の6乗を23で割った余り、サーバは8の15乗を23で割った余りを計算し、どちらも2になります。
この小例は実運用で使ってはいけません。小さい群では秘密値を容易に推測できます。実際のECDHEは規格化された安全な楕円曲線・グループと検証済み実装を使います。計算の要点は、公開値8と19を送っても秘密値6と15を送らず、双方が共有値2に到達することです。
5-2. ハンドシェイクの失敗点を順に読む
段階 | 失敗した場合の意味 |
|---|---|
ClientHello / ServerHello | 対応するTLS版や鍵共有グループが合わなければ接続が成立しない。選択結果が許可した安全な方式か確認する。 |
Certificate | 信頼するCAからの連鎖、名前、有効期間などを検証する。証明書が存在するだけでは`app.example`の証明にならない。 |
CertificateVerify | サーバが証明書に対応する秘密鍵を使い、ハンドシェイクの内容に署名したことを検証する。公開鍵を差し替えた中間者を排除する重要な段階。 |
Finished | 導出した鍵とハンドシェイクの記録が整合するか確認する。失敗すればアプリケーションデータを送る前に停止する。 |
Application Data | 成功した接続でも、利用者認証・権限・サーバ内部の処理は別途確認する。TLS成功だけで業務要求の正当性は決まらない。 |
TLS 1.3の鍵スケジュールは、早期秘密、ハンドシェイク秘密、マスター秘密から方向別の通信秘密を導きます。詳細なラベルはRFC 8446に定義されます。試験ではラベルを暗記するより、共有秘密Zとハンドシェイク全体の記録から複数の鍵が分離して導かれる点を押さえます。
5-3. セッション再開と0-RTTの検証
同じ端末が再接続するとき、セッションチケット由来のPSKを使えます。再開時に新しいDHEも行うモードなら、その接続の1-RTTデータについて前方秘匿性を評価できます。PSKだけのモードや0-RTT早期データまで一括して『ECDHEで守られた』と記載してはいけません。
APP-1が0-RTTで`POST /transfer`を受け取ると、通信を記録した攻撃者による再送で処理が重複し得ます。TLS層の再生対策だけへ依存せず、送金のような操作は0-RTTを拒否し、通常の1-RTT後に送る設計が分かりやすい選択です。アプリケーションの操作IDや重複排除も必要に応じて組み合わせます。
5-4. 事故調査でのタイムライン
『証明書鍵が14:00に盗まれた』場合、11:00の録画済み通信と15:00の新規通信を分けます。11:00の接続がECDHEなら後日の長期鍵だけでは復号しにくい一方、15:00には攻撃者が正規サーバを装う可能性があります。どちらも鍵ログの残存、0-RTT、端末侵害の有無を別に確認します。
復旧の確認には、旧証明書を提示するサーバが残っていないか、ロードバランサと全バックエンドの設定、証明書チェーンと鍵IDを点検します。正常なクライアントから接続し、選択されたTLS版、鍵共有グループ、証明書検証、0-RTT方針を記録します。設定ファイルの更新だけでは実際の合意結果を証明できません。
6. 科目B(午後)の判断と演習
設問では、『攻撃者が何をいつ得たか』『対象は1-RTTか0-RTTか』『証明書検証は有効か』を三つの列に分けます。ECDHEは共有秘密を得る技術、証明書と署名は相手の認証、AEADは通信内容を守る技術です。役割の混同を避けます。
演習1:秘密値の送信
条件:端末とAPP-1がECDHEで鍵交換した。質問:両者は一時秘密値を送信するか。解答:しない。公開値を交換し、それぞれが共有秘密を計算する。誤答『秘密鍵を暗号化して送る』はDHの基本を取り違えている。
演習2:後日の証明書鍵漏えい
条件:録画済み1-RTT通信はECDHEで、接続の一時秘密と通信鍵は破棄され、後日サーバ証明書秘密鍵だけが漏れた。質問:過去通信を復号できるか。解答:その鍵だけではできない。誤答『秘密鍵なら全部読める』は認証鍵と通信鍵を混同している。
演習3:鍵ログ
条件:ECDHE接続の通信鍵がSSLKEYLOGFILEに残り漏れた。質問:PFSを根拠に安全といえるか。解答:いえない。対象通信の鍵自体が漏れている。誤答はPFSの前提を無視している。
演習4:証明書検証無効
条件:クライアントが証明書名の検証を無効化した。質問:ECDHEで中間者を防げるか。解答:防げない。鍵交換相手の認証を失う。誤答『鍵交換が強いから安全』は相手確認を省いている。
演習5:0-RTT
条件:送金APIを0-RTTで呼ぶ案が出た。質問:何を懸念するか。解答:0-RTTデータの再生による重複処理とPFS欠如。無効化か、アプリ側の重複排除などを検討する。誤答『TLS 1.3だから安全』は早期データの性質を無視している。
演習6:失効後の確認
条件:APP-1の証明書秘密鍵を更新した。質問:復旧完了には何を確認するか。解答:旧鍵の失効・停止、新証明書の名前とチェーン、クライアントでの検証、なりすまし期間の調査。誤答『証明書ファイルを置いた』は実効を確認していない。
7. 一次資料
この記事についてAIに深掘り質問する
ChatGPT、Claude、Perplexityにこの記事を参照させ、要点の確認や疑問点を自由に質問できます。
次におすすめの学習
編集・検証について
編集・検証:IT資格ラボ編集部
IPAが公開する試験要綱・シラバス・過去問題と、各技術の公式資料を優先して内容を確認しています。制度変更や誤りを確認した場合は、記事を見直して更新します。
編集方針・情報源・訂正方針を見る