✅ TLS 1.2 における RSA方式の鍵交換の流れ
▼ 1. クライアント Hello
- クライアントはまず、サーバに「ClientHello」メッセージを送る。
- ここには以下が含まれる:
- サポートするTLSのバージョン
- サポートする暗号スイート(例:RSA、AESなど)
- 乱数(クライアントランダム)
- その他オプション情報
▲ 2. サーバ Hello
- サーバは「ServerHello」メッセージで応答する。
- サーバの選択した:
- TLSバージョン
- 暗号スイート
- サーバの乱数(サーバランダム)
▲ 3. サーバ証明書の送信
- サーバは自分の公開鍵証明書(X.509証明書)をクライアントに送信。
- 証明書の中に、サーバのRSA公開鍵が入っている。
- 証明書は認証局(CA)によって署名されていて、クライアントはその正当性を検証する。
▼ 4. クライアントが Pre-Master Secret を生成
- クライアントは、ランダムなPre-Master Secret(48バイトのランダム値)を生成。
- そして、そのPre-Master Secretをサーバの公開鍵でRSA暗号化する。
▼ 5. クライアントキー交換
- 暗号化されたPre-Master Secretを「ClientKeyExchange」メッセージとしてサーバに送信。
▲ 6. サーバが Pre-Master Secret を復号
- サーバは自分のRSA秘密鍵で復号し、Pre-Master Secretを得る。
▼▲ 7. 共通鍵の生成
- クライアントとサーバはそれぞれ、以下の情報から同じ共通鍵(セッション鍵)を導出:
- Pre-Master Secret
- クライアントランダム
- サーバランダム
- これにより、共通の暗号鍵・MAC鍵などが生成される。
この3つの値を材料として、TLS 1.2では:
Markdown
マスターシークレット = PRF(Pre-Master Secret, "master secret", ClientRandom + ServerRandom)
という手順でマスターシークレットが生成されます。
さらにこのマスターシークレットから、
Markdown
セッション鍵(共通鍵) = PRF(Master Secret, "key expansion", ServerRandom + ClientRandom)
のようにして、実際に通信に使う暗号鍵・MAC鍵などが生成されます。
※この際の"master secret"
や"key expansion"
は固定の文字列で、どの用途の鍵を作るのか区別するために使われます。
✅【PRFとは】
- Pseudo-Random Function(擬似乱数生成関数)
- TLSの仕様の中で、「こういうアルゴリズムで計算しなさい」と定義されています。
- TLS1.2では**HMAC(SHA-256などのハッシュ関数)**をベースに実装されています。
▼▲ 8. Finished メッセージで確認
- その後、クライアントとサーバは、共通鍵を使って「Finished」メッセージを交換し、お互いに正しい鍵が共有できたことを確認。
✅ 【まとめ図】
Markdown
1. ClientHello (クライアント乱数 + 暗号スイート)
2. ServerHello (サーバ乱数 + 暗号スイート選択)
3. サーバ証明書 (RSA公開鍵含む)
4. Pre-Master Secret 生成
5. Pre-Master Secret を公開鍵で暗号化し送信
6. サーバが秘密鍵で復号
7. Pre-Master Secret + 両者の乱数 → 共通鍵
8. Finishedメッセージ交換 → 暗号通信開始
✅ 【ポイント】
- クライアントだけがPre-Master Secretを生成する。
- サーバは復号するだけで、自分では鍵は作らない。
- Pre-Master Secretと乱数2つから鍵素材(共通鍵)ができる。
- RSA方式はサーバ秘密鍵が漏れると過去のPre-Master Secretも解読できるためForward Secrecyが無い。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
✅【TLS 1.2 における DHE 鍵交換の流れ】
✅【前提:DHEとは】
- DHE(Ephemeral Diffie-Hellman)は、セッションごとに一時的な鍵(エフェメラル鍵)を使って共通鍵を生成する仕組み。
- Forward Secrecy(前方秘匿性)があり、もしサーバの秘密鍵が漏れても過去の通信は解読されない。
🔵 ① クライアント Hello
- クライアントはClientHelloをサーバに送信。
- そこに:
- サポートする暗号スイート(例:TLS_DHE_RSA_WITH_AES_128_CBC_SHA など)
- TLSのバージョン
- クライアントのランダム値(クライアントランダム)
などを含める。
🌑② サーバ Hello
- サーバはServerHelloを返し、
- 選択した暗号スイート(ここではDHEを含むもの)
- TLSバージョン
- サーバランダム
を送る。
🌑③ サーバ証明書の送信
- サーバは、自身の公開鍵証明書(X.509証明書)を送信。
- 証明書にはRSAの公開鍵などが入っていて、「サーバの正当性確認のため」に使われる。
- (DHEでは、このRSA鍵で署名するために使う)
🌑④ サーバのDHEパラメータ送信(ServerKeyExchange)
- サーバは以下の情報を送信:
- p(素数)
- g(生成元)
- サーバのDHE公開値:g^b mod p(bはサーバの秘密値)
- これらに対するRSA署名(サーバ証明書の秘密鍵で署名)
こうすることで、「このDHEパラメータは正当なサーバが送ったものだよ」と証明している。
🔵 ⑤ クライアントのDHEパラメータ送信
- クライアントは、ランダムな秘密値aを選び、
- クライアントの公開値:g^a mod p
を計算し、ClientKeyExchangeメッセージでサーバに送る。
- クライアントの公開値:g^a mod p
🔵🌑 ⑥ 双方が共通鍵素材(Pre-Master Secret)を計算
- クライアント側:
Markdown
(g^b mod p)^a mod p
= g^(ab) mod p
- サーバ側:
Markdown
(g^a mod p)^b mod p
= g^(ab) mod p
→ クライアントとサーバが同じ値(g^(ab) mod p)を得る。これがPre-Master Secretになる。
🔵🌑 ⑦ Pre-Master Secret + ランダム値 → 共通鍵生成
- 双方はPre-Master Secretと
- クライアントランダム
- サーバランダム
をPRF関数に入れて、マスターシークレットを生成。
- さらにマスターシークレットから、セッション鍵(共通鍵)が計算される。
🔵🌑 ⑧ Finished メッセージ交換
- 共通鍵を用いて、Finishedメッセージを暗号化して交換。
- お互いの鍵が一致していれば復号が成功し、ここから安全な通信が始まる。
✅【まとめ図】
Markdown
1. ClientHello(クライアントランダム、対応暗号スイート)
2. ServerHello(サーバランダム、選択暗号スイート)
3. Certificate(サーバの証明書)
4. ServerKeyExchange(p, g, g^b mod p, 署名)
5. ClientKeyExchange(g^a mod p)
6. 両者で g^(ab) mod p を計算 → Pre-Master Secret
7. Pre-Master Secret + ランダム2種 → PRF → マスターシークレット
8. マスターシークレット → 共通鍵(セッション鍵)
9. Finishedメッセージ交換
- RSA方式と違い、Pre-Master Secretは両者が計算で得る。
- サーバ証明書のRSA鍵は「署名検証」のみで、暗号化には使わない。
- Forward Secrecyあり(秘密鍵が漏れてもg^bが漏れない限り安全)