TLS証明書の基礎③|ブラウザは証明書をどう確かめる?エラーの原因も

TLS証明書の基礎③|ブラウザは証明書をどう確かめる?エラーの原因も TLS証明書

「証明書エラーが出ました」。この一言から、情シスの調査が始まります。でも、エラーの理由は、期限切れ、名前の違い、中間証明書の不足、信頼されないルートなど、いくつもあります。理由を切り分けるには、ブラウザが、何を、どの順番で確かめているのかを、証明書検証の流れとして知っておくのが近道です。

シリーズ「TLS証明書の基礎」の第3回は、ブラウザによる証明書検証の流れを整理します。第1回、第2回で出てきた、サーバー証明書、中間証明書、ルート証明書が、実際の通信の中で、どう使われるのかを見ていきます。

証明書検証の結論:ブラウザは「5つのこと」を確かめている

先に結論です。ブラウザは、サイトに接続するとき、証明書について、次の5つを確かめています。

確認 見ること 失敗の原因の例
1. 名前 接続先の名前が、証明書に書かれているか 別のドメインの証明書を、設定している
2. 期限 有効期間に入っているか 更新を忘れて、期限切れ
3. 署名・チェーン 署名が正しく、ルートまでつながるか 中間証明書を、サーバーに設定していない
4. 信頼 たどり着いたルートが、信頼ストアにあるか 自己署名証明書、社内CAのルートが未登録
5. 失効 証明書が、取り消されていないか 秘密鍵の漏えいなどで、失効された

証明書検証の流れ:接続からチェーンの確認まで

TLSで接続するときの流れを、図にしました。

ブラウザがサーバーに接続し、証明書チェーンを受け取って、5つの確認をする流れの図

流れを、順に言葉にします。

  1. ブラウザが、サーバーに接続します。 このとき、「example.com に接続したい」という、サイトの名前も伝えます。
  2. サーバーが、証明書チェーンを送ります。 中身は、サーバー証明書と、中間CA証明書です。ルート証明書は、ふつう送りません。ブラウザが、すでに持っているからです。
  3. ブラウザが、5つの確認をします。 1つでも失敗すると、警告が出ます。
  4. 確認に成功すると、暗号化の鍵を決めて、通信を始めます。 画面には、鍵のマークが出ます。

ポイントは、2番の「サーバーが中間CA証明書も送る」ところです。サーバーに、サーバー証明書だけを設定して、中間CA証明書を設定し忘れると、ブラウザは、ルートまで、たどれなくなります。

失効の確認:証明書は、期限の前でも取り消される

5番の失効は、あまり意識されませんが、大事な確認です。証明書は、有効期限の前でも、取り消されることがあります。たとえば、秘密鍵が漏れた、発行の手続きに間違いがあった、などの場合です。

取り消された証明書の一覧を、失効情報といいます。ブラウザやOSは、さまざまな方法で、これを確かめます。

方法 内容
CRL(失効リスト) 取り消された証明書の一覧を、認証局が公開する
OCSP 特定の証明書が失効しているかを、認証局に問い合わせる
ブラウザ独自の失効リスト ブラウザやOSの更新で、失効情報をまとめて配る

ここで大事なのは、失効の情報が、すべてのソフトに、同じように届くわけではないことです。ブラウザは、更新で、素早く対応できます。一方、更新されていないアプリや機器は、失効した証明書を、そのまま信頼してしまうことがあります。第4回の事件の話で、この点が出てきます。

証明書検証をコマンドで確かめる:OpenSSLで見る

ブラウザの動きは、コマンドでも再現できます。OpenSSLの s_client で、検証の結果を見られます。

# 検証の結果と、名前の確認を表示する
echo | openssl s_client -connect gadgetzine.blog:443 -servername gadgetzine.blog -verify_hostname gadgetzine.blog 2>&1 | grep -E "Verify return code|Verified peername"

このブログで実行した結果(2026年10月30日に確認)です。

Verified peername: gadgetzine.blog
Verify return code: 0 (ok)

Verified peername は、名前の確認に成功した、という意味です。Verify return code: 0 (ok) は、チェーンの検証に、成功した、という意味です。

期限は、-checkend で確かめられます。指定した秒数のあいだに、期限が来るかを調べます。

# 30日(2,592,000秒)以内に、期限が切れるか確認する
echo | openssl s_client -connect gadgetzine.blog:443 -servername gadgetzine.blog 2>/dev/null | openssl x509 -noout -checkend 2592000

「Certificate will not expire」と出れば、30日以内には、切れません。「Certificate will expire」と出たら、更新の準備を始める合図です。

証明書エラーの原因を切り分ける:テスト用サイトで見る

エラーの原因ごとに、どんな結果になるかを、テスト用のサイト(badssl.com)で試してみました。結果は、次のとおりです(2026年10月30日に確認)。

状況 OpenSSLの結果 原因
期限切れ(expired.badssl.com) 10 (certificate has expired) 有効期限が切れている
自己署名(self-signed.badssl.com) 18 (self-signed certificate) 認証局ではなく、自分で署名している
信頼されないルート(untrusted-root.badssl.com) 19 (self-signed certificate in certificate chain) チェーンの終点が、信頼ストアにない
中間証明書の不足(incomplete-chain.badssl.com) 21 (unable to verify the first certificate) サーバーが、中間CA証明書を送っていない

ブラウザでは、同じ原因が、NET::ERR_CERT_DATE_INVALID(期限)、NET::ERR_CERT_AUTHORITY_INVALID(信頼できない発行者)、NET::ERR_CERT_COMMON_NAME_INVALID(名前の不一致)のような、エラーコードで表示されます。画面のコードと、上の表を、見比べると、原因の見当がつきます。

あるある:警告を「詳細設定 → 進む」で、通してしまう

証明書の警告が出たとき、「詳細設定 → 進む」を押して、通してしまうことがあります。開発中の自分のサーバーなら、まだよいのですが、本番のサイトや、外部のサービスで、同じことをするのは危険です。警告は、「相手が本物か、確かめられません」という意味だからです。

ごはんにたとえるなら、賞味期限が切れているお弁当に、「たぶん大丈夫」と、手を出すようなものです。原因を、切り分けてから、判断する。この回の表が、切り分けの出発点になります。

今回のまとめと次回予告

項目 内容
確認する5つ 名前・期限・署名とチェーン・信頼・失効
サーバーが送るもの サーバー証明書と中間CA証明書(ルートは、ふつう送らない)
失効 方法はいくつかあり、すべてのソフトに、同じように届くとは限らない
コマンド openssl s_client で、検証の結果、名前、期限を確かめられる

次回は、これまでの基礎の応用編です。最近話題になった、eMudhra の中間CAの鍵の問題を題材に、「中間CAの鍵が漏れると、何が困るのか」と、自分たちの環境で確かめることを、1本にまとめます。

→ 第4回:中間CAの鍵が漏れると何が起きる?eMudhraの事件と備え

ほかのセキュリティの話題は、当ブログの技術ネタからどうぞ。

参考

証明書検証の流れと確認する5つを、1枚にまとめた図

ITもごはんも、腹八分目が長続きのコツ!

コメント