仕上げは AI との協働でやっています。事実と表現は著者本人が確認しています。
「公開鍵暗号は安全だけど遅い、共通鍵暗号は速いけど鍵の共有が難しい」
セキュリティの教科書ではほぼ必ずこの一文が出てくる。試験対策としては暗記すれば済むが、なぜそうなのか・実際の通信ではどう組み合わされているのか は、テキストの説明だけでは輪郭が掴みにくい。
TLS (Transport Layer Security) のハンドシェイクは、この2つの暗号を実際にどう組み合わせて使っているかの教科書的な例になる。ハンドシェイクの中身を順に見ていくと、「ハイブリッド暗号」と呼ばれる方式が何を解いているのかが具体的に見える。
本記事は 実務的視点で見つめるITパスポート・セキュリティ編 の派生記事として、試験対策レベルの「家の鍵と鍵穴」比喩で押さえた上で、TLS 1.2/1.3 のハンドシェイクを RFC レベルで追う詳細編 を扱う。概念整理は元記事を参照のこと。
速さの差は実測でどれくらい違うか
「公開鍵暗号は遅い」と書かれていても、ピンと来ないことが多い。OpenSSL でベンチマークを取れば、実数で見える。
openssl speed rsa2048
openssl speed aes-256-cbc
手元の環境 (Apple M2 Max, arm64, LibreSSL) で叩いた結果はこの程度のオーダーだった。
| 暗号方式 | 種類 | 実測例 (オーダー) |
|---|---|---|
| RSA-2048 sign | 公開鍵暗号 (秘密鍵で署名) | 1 秒あたり数百回程度 |
| RSA-2048 verify | 公開鍵暗号 (公開鍵で検証) | 1 秒あたり数万回程度 |
| AES-256-CBC | 共通鍵暗号 | 1 秒あたり数百 MB 程度 |
絶対値は CPU や実装 (LibreSSL / OpenSSL / BoringSSL) で変わるので、 実機で叩いた時の桁感として読んでほしい。 大事なのは、 RSA は秒あたり回数で測る世界、 AES は秒あたりバイト数で測る世界、 という比較のものさし自体が違うこと。
理由は処理しているものの大きさが違うからだ。RSA は 2048 ビット (= 約 617 桁の十進数) の整数のべき剰余演算を 1 回 1 回やっている。AES は 128 ビット (= 16 バイト) のブロックに対して固定回数のビット演算を回しているだけ。設計目的が違うので、 性能特性もそのまま設計に従う。
ファイル全体や HTTP body を RSA で暗号化すると、転送が成立しないレベルで遅くなる。速度が問題で、公開鍵暗号は本番のデータ暗号化には使えない、というのが現実的な制約になる。
共通鍵暗号の問題: 鍵の共有
ではすべて AES で済ませればいいかというと、こちらは別の問題を持っている。送受信者が同じ鍵を持つ必要がある が、その鍵をどうやって安全に共有するかが解けない。
- 鍵をメールで送る → メールが盗聴されたら鍵が漏れる
- 鍵を別のサーバに置いてダウンロード → そのサーバへの通信が盗聴されたら漏れる
- 鍵を事前に手渡し → 不特定多数の Web サイトでは現実的でない
公開鍵暗号がここで効いてくる。公開鍵で暗号化した内容は対応する秘密鍵でしか復号できないので、「相手の公開鍵を入手して、それで AES の鍵を暗号化して送る」 が成立する。受信側は自分の秘密鍵で復号して、AES の鍵を取り出し、以降の通信は AES で行う。
これが「ハイブリッド暗号」と呼ばれる方式で、TLS の中身もほぼこれに沿っている。
TLS ハンドシェイクの中で何が起きているか
TLS 1.2 の RSA 鍵交換ベースの場合、ハンドシェイクはざっくり以下の流れになる (TLS 1.3 では Ephemeral Diffie-Hellman に置き換わっているが、考え方の対比のため 1.2 を例にする)。
ここで動いている暗号方式を整理すると:
| ステップ | 使う暗号 | 何をしているか |
|---|---|---|
| Certificate の検証 | 公開鍵暗号 (RSA) + デジタル署名 | サーバーが本物かを認証局の署名で確認 |
| Premaster Secret の暗号化 | 公開鍵暗号 (RSA) | クライアントが生成した鍵の素を、サーバーの公開鍵で暗号化して送る |
| 以降のデータ通信 | 共通鍵暗号 (AES) | ハンドシェイクで作った共通鍵で実データを暗号化 |
「鍵を交換するためだけに公開鍵暗号を使い、データの暗号化は共通鍵暗号を使う」 という分業が、TLS の設計に組み込まれている。公開鍵暗号は遅いが、鍵交換は1回だけなので遅さが許容範囲に収まる。
TLS 1.3 で何が変わったか
TLS 1.3 では、RSA 鍵交換と固定 Diffie-Hellman が標準スイートから外され、Ephemeral Diffie-Hellman 鍵交換 ((EC)DHE: 楕円曲線版 ECDHE と有限体版 DHE のどちらか) が必須になった。実装で広く使われるのは ECDHE 側だが、RFC 8446 §7.4 では Finite Field DHE もサポート対象として定義されている。
| 項目 | TLS 1.2 (RSA) | TLS 1.3 (ECDHE) |
|---|---|---|
| 鍵交換 | サーバーの公開鍵で暗号化して送る | クライアントとサーバーが共通鍵を「導出」する |
| Forward Secrecy | なし | あり |
| ハンドシェイクのラウンド数 | 2 RTT | 1 RTT (0 RTT モードもあり) |
Forward Secrecy が新しい論点になっていて、これは「過去の通信を、サーバーの秘密鍵が後から漏れても復号できない」という性質を指す。RSA 鍵交換だと、サーバーの秘密鍵が漏れた場合、過去に記録された通信ログから AES 鍵を遡って復元できてしまう。Diffie-Hellman 鍵交換は鍵を「都度導出」するので、後から復元できない。
ハイブリッド暗号の枠組みは TLS 1.3 でも変わらない (公開鍵系で鍵を作り、共通鍵で本番通信)。鍵を「送る」から「都度導出する」への変更が、Forward Secrecy を成立させている部分。
デジタル署名と認証局の話
ハンドシェイクの最初に出てきた「サーバー証明書」は、公開鍵暗号のもう1つの使い方であるデジタル署名で成り立っている。
認証局 (CA) が自分の秘密鍵で署名し、その署名は CA の公開鍵で検証できる。クライアントは事前に「信頼できる CA の公開鍵リスト」を持っていて、そのいずれかの CA の署名が付いていれば証明書を信頼する、という設計になっている。
これも公開鍵暗号と共通鍵暗号の役割分担で説明できる:
| 役割 | 使う暗号 |
|---|---|
| 「この公開鍵は本当にこのドメインのものか」を保証 | 公開鍵暗号 (デジタル署名) |
| 「この通信内容は改ざんされていないか」を保証 | 共通鍵暗号 (MAC) または公開鍵暗号 (署名) |
| 「この通信内容は盗聴されないか」を保証 | 共通鍵暗号 (AES) |
公開鍵暗号は「身元保証」と「鍵交換」の2つの役割を持っていて、共通鍵暗号は「データ暗号化」と「改ざん検知」を担当している。両者の役割が分かれているのは、速度と機能のトレードオフの結果として今のハイブリッド方式に落ち着いた、という経緯がある。
実務で触る時に効く知識
セキュリティ実務で TLS 周りを触ると、公開鍵と共通鍵の使い分けを意識する場面が出てくる:
| 場面 | どちらを意識するか |
|---|---|
| TLS の暗号スイート選定 | 公開鍵暗号 (RSA/ECDHE) と共通鍵暗号 (AES-GCM/ChaCha20) の組を選ぶ |
| 証明書の管理 | 公開鍵暗号 (秘密鍵を守る・公開鍵を配布する) |
| API トークンの暗号化保存 | 共通鍵暗号 (KMS等で鍵を管理) |
| JWT の署名 | 公開鍵暗号 (RS256/ES256) または共通鍵暗号 (HS256) |
| ファイル暗号化バックアップ | 共通鍵暗号 (AES) + 鍵を公開鍵で暗号化 (ハイブリッド) |
特に JWT の HS256 vs RS256 の選択は、ハイブリッド暗号の理解が直結する。HS256 は共通鍵暗号で速いが、検証者側も同じ鍵を持つ必要がある。RS256 は公開鍵暗号で、検証側は公開鍵だけ持てばよく、署名側だけ秘密鍵を持てば済む。マイクロサービス間で JWT を渡し合うなら RS256、単一サービス内で完結するなら HS256、という選択軸がここから出てくる。
振り返って
「公開鍵暗号は遅い・共通鍵暗号は速い」という暗記をしている時点では、なぜ TLS が両方使うのかは見えにくい。ハンドシェイクの中身を順に追って、「鍵の共有問題を公開鍵暗号で解いて、そこから先のデータ暗号化は共通鍵暗号でやる」という分業が具体的なシーケンスとして見えると、ハイブリッド暗号の必然性が腑に落ちる。
実務で触る時にも、認証 (= 身元保証) と暗号化 (= 盗聴対策) と改ざん検知 (= 完全性) の3つは別の技術で支えられている、という意識を持っておくと、トラブル時にどこを疑うかの判断が速くなる。
参考
- 関連記事 (概念整理): 実務的視点で見つめるITパスポート・セキュリティ編 — 公開鍵/共通鍵の比喩で押さえる試験対策編
- RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3
- RFC 5246: TLS Protocol Version 1.2
- RFC 7518: JSON Web Algorithms (JWA) — HS256/RS256/ES256 定義
- OpenSSL speed コマンド (ベンチマーク)
- Cloudflare blog: A Detailed Look at RFC 8446 (TLS 1.3)