ゆめさくセキュリティ

レッスン 1-4

TLS 1.3 の中身

鍵の印が守る物と、守らない物を切り分けます。

TLS が守るのは、相手が本物であること、途中で読まれないこと、途中で書き換えられないことの 3 つです。証明書の確かめを切ると 1 つ目が消え、残りの 2 つも意味を失います。守らない物 (データの長さ、0-RTT のデータの再送、届いた先の中身) と、記録での見え方、直ったことを試験で確かめる方法までを扱います。

  • 目安60 分
  • 出典を確かめた日2026年10月24日
  • 修了の条件TLS が守る物と守らない物を、3 つずつ挙げられる

なぜ通るのか

社内の請求の仕組みが、別のサーバーの API (外から呼べる窓口) に HTTPS で問い合わせているとします。開発中に証明書のエラーが出たので、誰かが「確かめない」設定にして通しました。動いたので、そのまま本番に出ました。

この設定のままでも、通信は暗号化されています。それでも守りは崩れています。TLS (通信を暗号化し、相手を確かめる決まり) の守りは、いくつかの前提の上に立っているからです。

TLS が守る 3 つ

TLS 1.3 の仕様 RFC 8446 は、守る性質を 3 つに分けています。

性質意味
認証サーバーの側は必ず確かめる。利用者の側は選べる
機密性確立したあとのデータは、両端にだけ見える
完全性途中で書き換えると、必ず気づける

仕様は、通信路を攻め手がすべて握っていても、この 3 つが成り立つように作るとしています。鍵の交換は毎回使い捨ての鍵で行うので、あとでサーバーの鍵が漏れても、過去の通信は読めません。これを前方秘匿性と呼びます。

どの前提が崩れると破られるか

暗号化と書き換えの検知は、「話している相手が本物だ」という前提の上でだけ意味を持ちます。偽物と鍵を交換してしまえば、暗号化された通信をその偽物が開いて読み、書き換えて本物へ送り直せます。

相手が本物かは、証明書で確かめます。確かめるのは 2 つです。

  • 証明書が、信じている CA (証明書を発行する機関) から順にたどれるか
  • 証明書に書かれた名前が、つなぎに行った名前と合うか

名前の照らし合わせについては RFC 9525 が、証明書の SAN (別名の欄) だけを見るよう定めています。どちらか片方を切るだけで、認証は消えます。

守らない 3 つ

正しく使っても、TLS が守らない物があります。

守らない物理由
データの長さRFC 8446 は長さを隠さないと書く。埋め草で紛らわすことはできる
0-RTT のデータ再送されない保証が無く、前方秘匿性も無い
届いた先の中身両端では平文に戻る。サーバーの中のデータは別に守る

0-RTT は、前に話した相手との間で、最初の往復を待たずにデータを送る仕組みです。速くなる代わりに、同じデータを送り直されても気づけないことがあります。だから、繰り返すと困る操作には使いません。

脆いコードと直したコード

ラボの中で比べます。自分で作った CA と、その CA が 127.0.0.1 に出した証明書を持つサーバーを手元で動かします。もう 1 台、その CA と関係の無い証明書を持つサーバーも、同じ 127.0.0.1 で動かします。これが偽物の役です。Python に付いている ssl と urllib だけで動きます。

確かめを切るか、自分の CA で確かめるか

脆いコード証明書の確かめを切る
def fetch(url, ca=None):ctx = ssl.create_default_context()ctx.check_hostname = Falsectx.verify_mode = ssl.CERT_NONEwith urlopen(url, context=ctx) as r:return r.read()
直したコード信じる CA を渡して確かめる
def fetch(url, ca):ctx = ssl.create_default_context(cafile=ca)with urlopen(url, context=ctx) as r:return r.read()

脆い方は、本物にも偽物にも同じようにつながり、どちらからも応答を受け取ります。直した方は、偽物につなぐと握手の途中で止まります。ca には自分のラボの CA のファイルを渡します。本番では、OS に入っている CA の一覧をそのまま使い、引数は要りません。

名前の確かめだけを切る

脆いコードCA は確かめるが名前を見ない
def fetch(url, ca):ctx = ssl.create_default_context(cafile=ca)ctx.check_hostname = Falsewith urlopen(url, context=ctx) as r:return r.read()
直したコード名前の照らし合わせは既定のまま
def fetch(url, ca):ctx = ssl.create_default_context(cafile=ca)with urlopen(url, context=ctx) as r:return r.read()

同じ CA が別の名前 (shop.example) に出した証明書を 127.0.0.1 で掲げると、脆い方は通ります。CA が正しくても、誰に出した証明書かを見なければ、その CA から証明書を得た誰にでもつながってしまいます。

ログでの見え方と検知

直した方が偽物につないだとき、Python は次のような例外を残します。

記録関係の無い証明書のとき
ssl.SSLCertVerificationError:[SSL: CERTIFICATE_VERIFY_FAILED]certificate verify failed:self-signed certificate
記録名前が合わないとき
certificate verify failed:IP address mismatch,certificate is not validfor '127.0.0.1'.

この例外は、守りが働いた証拠です。消すために確かめを切るのではなく、なぜ出たのかを調べます。守る側は次を見張ります。

見る物なぜ効くか
コードの中の確かめを切る設定CERT_NONE などは書いた時点で見つけられる
証明書の確かめの失敗の数急に増えたら、偽物か設定の誤りを疑う
証明書の期限切れると止まる。検査の装置なら黙って見えなくなる

最後の行は、関わる事例で見る失敗そのものです。

直し方と、直ったことの確かめ方

自分の PC の中だけで行います。待ち受けは 127.0.0.1 に固定し、外のサービスには向けません。

  1. 作業用のフォルダで、ラボの CA と、その CA が 127.0.0.1 に出した証明書を作る (SAN に 127.0.0.1 を入れる。新しい Python は厳しく確かめるので、CA には CA であることの印、サーバーの証明書には発行者の鍵の印も付ける)
  2. 関係の無い証明書と、同じ CA が別の名前に出した証明書も作り、3 台のサーバーを 127.0.0.1 で動かす
  3. 脆い fetch が 3 台すべてから応答を受け取ることを確かめる
  4. 直したコードに置き換え、本物だけに通り、残りの 2 台では例外になることを確かめる
  5. 下の試験を足し、確かめを切るコードに戻すと試験が落ちることも確かめる
  6. 終わったら、サーバーを止め、鍵と証明書を作業用のフォルダごと消す
Python直ったことを固める試験
def test_trusted_server(real, ca):assert fetch(real, ca) == b"hello" def test_unrelated_cert(fake, ca):with pytest.raises(URLError):fetch(fake, ca) def test_wrong_name(other, ca):with pytest.raises(URLError):fetch(other, ca)

試験は「同じ偽物に対して、直す前は通り、直したあとは止まる」ことを固定します。あとで誰かがエラーを消すために確かめを切っても、ここで止まります。

あわせて、サーバー側の設定は IPA の TLS 暗号設定ガイドラインで点検します。ガイドラインは 3 つの設定基準を設け、特段の事情が無ければ「推奨セキュリティ型」を勧めています。使う版、サーバー証明書、暗号の組み合わせごとに、満たすべき項目をチェックリストにしてあります。証明書の期限は、openssl の checkend のように残りの日数を機械で見て、切れる前に知らせます。

関わる事例

Equifax では、2017年3月7日に公開された Apache Struts の脆弱性が、オンラインの苦情受付の窓口で修正されないまま突かれました。

TLS に関わるのは、そのあとです。暗号化された通信を検査する装置の証明書が期限切れで、持ち出しの通信が検査されていませんでした。米下院の報告書によると、証明書は2016年1月31日に失効しており、19か月のあいだ検査できていませんでした。期限切れの証明書を更新した直後に、不審な通信に気づいています。

暗号化された通信を見るための装置も、証明書が切れれば何も見なくなります。証明書の期限の見張りと、見張る装置そのものが動いているかの見張りは、セットで要ります。

確認クイズ

1 問目

開発中に、社内の API への HTTPS の呼び出しで証明書のエラーが出ました。どう直すのがよいですか。

  • ア 確かめを切る設定にして、本番の前に戻す
  • イ エラーの理由を調べ、信じる CA か証明書の名前を正しく直す
  • ウ HTTPS をやめて HTTP にする
答えと理由を見る

答え イ

確かめを切ると、偽物とも鍵を交換してしまい、暗号化が守るはずの中身を偽物に渡します。「本番の前に戻す」は、戻し忘れたまま出る典型です。エラーは守りが働いた証拠なので、CA の渡し方か、証明書の SAN の名前を正しくします。

2 問目

TLS 1.3 で正しくつないでいても、守られない物はどれですか。

  • ア 途中での書き換え
  • イ 送ったデータの長さ
  • ウ サーバーが本物であること
答えと理由を見る

答え イ

RFC 8446 は、TLS がデータの長さを隠さないと書いています。書き換えの検知とサーバーの認証は、TLS が守る性質です。長さから中身を推し量られると困るときは、埋め草で長さをそろえるなど、別の手当てが要ります。

説明課題

次のことを、自分の言葉で 3 行にまとめてください。書けたら、このレッスンは修了です。

  • TLS が守る物と守らない物を、3 つずつ
模範解答を見る

TLS が守るのは、サーバーが本物であること、途中で読まれないこと、途中で書き換えられないことの 3 つだ。守らないのは、データの長さ、0-RTT で送ったデータの再送、両端で平文に戻ったあとの中身の 3 つだ。そして守る 3 つも、証明書の CA と名前を確かめたときに限って成り立つ。

一次資料

どれも 2026年10月24日に開いて、題と中身を確かめました。

次へ

次のレッスンは「認証の仕組み」です。TLS がサーバーを確かめたあと、利用者が本人かをどう確かめるのかを、パスワード、セッション、パスキーの順に扱います。

次のレッスン 1-5 認証の仕組み