ネットワーク●●●○○

TLS

TLS ・ てぃーえるえす

通信を暗号化し相手を確かめるプロトコル。公開鍵の技術で鍵を合意し、共通鍵で高速に守る。

✦ 30秒で試す — 航海世界中の暗号通信の信頼は、PCに最初から入っている証明書から始まる偽サイトを開いたとき、鍵マークは付くか?予想してみる

概要

TLS(Transport Layer Security)は、ネットワークの通信を暗号化し、盗聴・改ざん・なりすましから守るプロトコルです。HTTPS の「S」の中身がこれで、HTTP に限らず、メールの SMTP やデータベースへの接続など、さまざまなプロトコルの下敷きとして使われています。TCP/IP のトランスポート層とアプリケーション層の間に挟まる「暗号化の層」と考えると、位置づけがつかみやすくなります。

TLS の設計の核心は、2種類の暗号の合わせ技です。接続の最初に公開鍵暗号の技術を使って、盗聴者に知られずに「共通鍵」を合意し(この手順をハンドシェイクと呼びます)、あとの通信はその共通鍵による速い暗号で守ります。鍵を安全に共有できるが遅い公開鍵暗号と、速いが鍵の受け渡しが悩みの共通鍵暗号の、長所だけを組み合わせた構成です。さらに、サーバの証明書を検証して「相手が本物か」も確かめます。

「SSL」は前身の名前です。いま動いている実体はほぼすべて TLS ですが、「SSL 証明書」「SSL 化」という呼び名だけが慣習として残っています。

なぜ生まれたか

インターネットの基盤である TCP/IP は、互いを信頼できる研究者どうしのネットワークで生まれたので、暗号化の仕組みを持っていません。パケットは経路上のどの機器からも平文で読め、書き換えもできます。1990年代に Web で買い物が始まると、これは「カード番号が経路の途中で盗み放題」という深刻な問題になりました。

そこで Netscape 社が1994年に SSL(Secure Sockets Layer)を作りました。大事な設計判断は、HTTP を改造するのではなく、「TCP とアプリケーションの間に挟まる汎用の暗号化の層」として作ったことです。おかげで HTTP 以外のプロトコルもそのまま安全にでき、アプリケーションは暗号の細部を知らずに済みます。SSL 3.0 を土台に、標準化団体の IETF が引き継いで1999年に名前を変えたのが TLS 1.0 です。

その後の歴史は、見つかった脆弱性への対応の歴史でもあります。SSL 3.0 は POODLE、TLS 1.0 は BEAST といった攻撃で破られ、暗号の選び方の自由さそのものが弱点になりました。2018年の TLS 1.3(RFC 8446)は、危ない古い方式を仕様から削り、ハンドシェイクを1往復に縮めた大改訂です。

詳細

二段構え — 公開鍵で鍵を合意し、共通鍵で運ぶ

TLS 1.3 のハンドシェイクでは、ブラウザとサーバがそれぞれ使い捨ての秘密の値を作り、そこから計算した「公開値」だけを交換します。お互いに「自分の秘密」と「相手の公開値」を組み合わせると、同じ「共有の秘密」に行き着きます。これが ECDHE(楕円曲線ディフィー・ヘルマン鍵交換)です。盗聴者に見えるのは2つの公開値だけで、そこから共有の秘密を計算することは現実的にできません。共有の秘密から鍵導出関数(HKDF)で通信用の共通鍵を作り、あとのデータはその鍵で暗号化します。

ブラウザ秘密 a毎回つくり、捨てる公開値 Aa と B から共有の秘密 → 共通鍵サーバ秘密 b毎回つくり、捨てる公開値 B証明書の秘密鍵で署名b と A から共有の秘密 → 共通鍵ClientHello に AServerHello に B+証明書と署名(暗号化済み)盗聴者に見えるのは A と B だけA・B から共有の秘密は計算できないアプリのデータ: 共通鍵の AEAD で暗号化と改ざん検知を同時に
TLS 1.3 の二段構え。公開値の交換で共有の秘密に行き着き、そこから作った共通鍵で、あとのデータを暗号化と改ざん検知を一体にした AEAD で守る

秘密の値を接続ごとに作って捨てることには、もう1つ大きな意味があります。前方秘匿性(forward secrecy)です。昔の TLS には、ブラウザが作った共通鍵のもとを「サーバの証明書の公開鍵で暗号化して送る」RSA 鍵交換がありました。この方式だと、録りためた過去の通信も、何年か後にサーバの秘密鍵が漏れた時点でまとめて解読されてしまいます。ECDHE では通信の鍵が証明書の鍵と切り離されているので、証明書の秘密鍵が漏れても過去の通信は守られます。TLS 1.3 は RSA 鍵交換を廃止し、前方秘匿性のある方式だけにしました。

改ざんの検知も、TLS 1.3 では暗号化と一体です。AES-GCM や ChaCha20-Poly1305 といった AEAD(認証付き暗号)は、暗号化と同時に「1ビットでも書き換えられたら分かる」検証用のタグを付けます。TLS 1.2 以前の CBC という方式では、暗号化とは別に HMAC(ハッシュ化の関数を使ったメッセージ認証)で改ざんを検知していて、この2つの組み合わせ方の甘さという脆弱性を突く攻撃(Lucky Thirteen など)が何度も見つかりました。いまも HMAC は鍵の導出(HKDF)の中で使われていますが、データの保護は AEAD に任されています。

ハンドシェイク — 1往復でそろう

TLS 1.3 のハンドシェイクを時間の順に追うと、次のようになります。ブラウザは最初のあいさつ ClientHello に、使える暗号の候補と一緒に公開値(key_share)をもう入れてしまいます。サーバは ServerHello で自分の公開値を返した時点で共通鍵を計算できるので、そこから先の証明書や署名はすでに暗号化して送ります。

サーバブラウザサーバブラウザここから先は共通鍵で暗号化証明書の鎖と署名を検証するClientHello・暗号の候補・公開値 A・SNIServerHello・選んだ暗号・公開値 B証明書・CertificateVerify・FinishedFinishedHTTP リクエストHTTP レスポンス

CertificateVerify は、サーバが「ここまでのやり取り全体」に証明書の秘密鍵で署名したものです。これで、公開値 B を送ってきたのが証明書の持ち主本人だと確かめられます。TLS 1.2 では同じことに2往復かかり、証明書も平文で流れていました。TLS 1.3 では1往復で済み、一度つないだ相手への再接続なら、最初のパケットにデータを載せる 0-RTT も使えます(ただしリプレイされうるので、冪等性のあるリクエストに限ります)。

証明書と PKI — 「本物である」ことの保証

暗号化だけでは足りません。偽のサーバと「安全に」暗号化通信をしても意味がないからです。相手の身元を保証するのがサーバ証明書と認証局(CA)です。証明書は「この公開鍵はこのドメインの持ち主のものである」と CA が電子署名した文書です。CA はドメインの持ち主であることを確かめてから発行するので、攻撃者は正規のドメインの証明書を手に入れられません。これがなりすまし防止の根拠です。

実際には、ルート CA が直接サーバ証明書に署名することはほとんどありません。ルートの秘密鍵はオフラインの金庫にしまい、ルートが署名した中間 CA がふだんの発行を受け持ちます。ブラウザはサーバ証明書から発行者を1段ずつたどり、自分(または OS)の信頼ストアに最初から入っているルートに行き着けば、本物と判断します。ルート証明書そのものは自己署名ですが、信頼ストアに入っていること自体が信頼の根拠です。この仕組み全体を PKI(公開鍵基盤)と呼びます。

サーバが送る(TLS の Certificate メッセージ)ブラウザ・OS の信頼ストアサーバ証明書主体: shop.example発行者: 中間CA中間CA主体: 中間CA発行者: ルートCAルートCA主体: ルートCA発行者: 自分(自己署名)署名署名検証はサーバ証明書から発行者をたどり、信頼ストアのルートに行き着けば成功
証明書の信頼の連鎖。サーバが送るのはサーバ証明書と中間CAの証明書で、行き着く先のルートはブラウザの信頼ストアにある

下の部品で確かめてください。カードを運んでサーバが送る証明書を組むと、ブラウザの検証の門を順に通ります。ドメイン不一致・期限切れ・自己署名のカードに差し替えたり、ルートを信頼ストアから外したりすると、鎖のどこで切れるかが変わります。

⚡ 体験: 証明書の鎖をつないで、鍵マークを点ける
https://shop.example/まだ検証していないサーバが送る証明書(TLS の Certificate メッセージ)ブラウザの信頼ストア① サーバ証明書② 中間CAISRG Root X1発行者: 自分自身タップで外す① ← ② の署名発行者をたどる② ← ルート信頼ストアにあるか有効期限今日 2026-09-25ホスト名shop.example手元の証明書(つかんで上の枠へ)shop.example発行者: R11〜2026-10-30other.example発行者: R11〜2026-10-30shop.example発行者: R11〜2026-05-30shop.example発行者: shop.example〜2027-08-01R11発行者: ISRG Root X1〜2027-03-12

下のカードからサーバが送る証明書を選び、上の枠へ運んでください(タップでも置けます)。① にサーバ証明書、② に中間CA の証明書です。署名の鎖が信頼ストアのルートまでつながれば、鍵マークが点きます。

それでも、CA が間違って(あるいは攻撃されて)別人に証明書を発行してしまう事故は起こります。2011年にはオランダの CA、DigiNotar が侵入され、google.com などの偽の証明書が発行されて実際に使われました。これを受けて広まったのが Certificate Transparency(CT)です。CA は発行したすべての証明書を、誰でも検証できる追記専用の公開ログに登録し、ブラウザはログに登録された証拠(SCT)のない証明書を受け入れません。ドメインの持ち主はログを見張ることで、自分のドメインに身に覚えのない証明書が出ていないかを確かめられます。

実務での使いどころと落とし穴

実務で TLS を自分で実装することはまずなく、関心は「どこで終わらせるか」と「証明書をどう管理するか」です。多くの構成ではリバースプロキシやロードバランサ、CDN が TLS を終わらせ、アプリケーション本体は平文で受けます。サーバの設定では「TLS 1.2 以上だけを許し、推奨の暗号スイートを使う」が基本線で、SSL 3.0 や TLS 1.0・1.1 は主要ブラウザで無効になっています。証明書は Let’s Encrypt などで自動更新するのが定石で、「期限切れで全断」は今も定番の障害です。設定ミスの定番には、中間証明書の送り忘れもあります(多くのブラウザは救済してつながるので、特定のクライアントだけが失敗して気づきにくい)。

通常はサーバだけが証明書を示しますが、クライアントにも証明書を求めて双方向に認証するのが mTLS(相互 TLS)で、マイクロサービス間の通信を守るのによく使われます。

ハンドシェイクには往復のコストがあり、遠いサーバほど効いてきます(レイテンシとスループットの「レイテンシ」の側の問題です)。接続の使い回しやセッションの再開が性能に効くのはこのためです。HTTP/3とQUIC では、TLS 1.3 の鍵交換をトランスポートのハンドシェイクに組み込み、UDP の上で1往復にまとめています。

試問

ブラウザが https://shop.example/ に接続し、サーバから届いた証明書を検証します。手元の証明書のカードを「① サーバ証明書」「② 中間CA」の枠へ運ぶ(タップでも置ける)と、署名の鎖・ルート・有効期限・ホスト名の4つの門を順に確かめます。右のルート証明書をタップすると、ブラウザの信頼ストアから外したり戻したりできます。

✦ 命題挑戦中

鍵マークを点けたうえで、署名がすべて本物なのにブラウザが接続を止める場合を2通り作れ

  • 本物の鎖で鍵マークを点ける
  • 署名の鎖はすべて本物なのに、ホスト名の門で止まる接続を作る
  • 署名の鎖はすべて本物なのに、ルートの門で止まる接続を作る
⚡ 体験: 証明書の鎖をつないで、鍵マークを点ける
https://shop.example/まだ検証していないサーバが送る証明書(TLS の Certificate メッセージ)ブラウザの信頼ストア① サーバ証明書② 中間CAISRG Root X1発行者: 自分自身タップで外す① ← ② の署名発行者をたどる② ← ルート信頼ストアにあるか有効期限今日 2026-09-25ホスト名shop.example手元の証明書(つかんで上の枠へ)shop.example発行者: R11〜2026-10-30other.example発行者: R11〜2026-10-30shop.example発行者: R11〜2026-05-30shop.example発行者: shop.example〜2027-08-01R11発行者: ISRG Root X1〜2027-03-12

下のカードからサーバが送る証明書を選び、上の枠へ運んでください(タップでも置けます)。① にサーバ証明書、② に中間CA の証明書です。署名の鎖が信頼ストアのルートまでつながれば、鍵マークが点きます。