SSL/TLS入門 | サーバ証明書はなぜ信頼できる? CA・証明書チェーン・PKIの仕組み
はじめに
以前TLSハンドシェイクについての記事を書いたのですが、そもそもTLS通信で使われる「証明書」がどのように発行され、なぜブラウザはその証明書を信用できるのか、理解があやふやでした。
そこで今回は、
- サーバ証明書
- 中間証明書
- ルート証明書
- CA (認証局)
の関係を整理します。
登場人物
わかりやすいように、
太郎さんがexample.comというwebサイトを運営しており、DigiCertのような認証局からサーバ証明書を取得する
という例で考えます。なお、この記事では証明書の仕組みを理解することを目的としているため、実際のDigCertの証明書チェーンや運用をそのまま再現するのではなく、一部単純化しています。
登場人物 | 持っているもの | 役割 |
|---|---|---|
太郎さんのWebサーバ | TLS秘密鍵・TLS証明書 | example.comとしてwebサイトを提供 |
DigiCertの中間CA | 中間CA秘密鍵・中間証明書 | サーバ証明書を発行・署名する |
DigiCertのルートCA | ルートCA秘密鍵・ルート証明書 | 中間証明書を発行・署名する |
ブラウザ | Trust Store | 証明書チェーンを検証する |
各証明書は以下のような関係になっています。
┌──────────────────────────┐
│ DigiCertのルートCA
│
│ 持っているもの
│ ・ルートCA秘密鍵
│ ・ルートCA公開鍵
└──────────────────────────┘
│
│ ルートCA秘密鍵で
│ 中間証明書に署名
▼
┌──────────────────────────┐
│ 中間証明書
│
│ ・中間CAの公開鍵
│ ・中間CAの情報
│ ・有効期間
│ ・ルートCAによる署名
└──────────────────────────┘
┌──────────────────────────┐
│ DigiCertの中間CA
│
│ 持っているもの
│ ・中間CA秘密鍵
│ ・中間CA公開鍵
└──────────────────────────┘
│
│ 中間CA秘密鍵で
│ サーバ証明書に署名
▼
┌──────────────────────────┐
│ example.comのサーバ証明書
│
│ ・example.com
│ ・サーバ公開鍵
│ ・有効期間
│ ・中間CAによる署名
└──────────────────────────┘つまり、
- ルートCAの秘密鍵→中間証明書に署名する
- 中間CAの秘密鍵→サーバ証明書に署名する
- サーバ秘密鍵→CAによる証明書発行には渡さず、Webサーバ側で保持する
という関係です。この関係を頭に入れた上で、太郎さんが証明書を取得する流れを見ていきます。
そもそもCAとは
CA (Certificate Authority / 認証局)とは、信頼された証明書を発行する機関です。DigiCert, GlobalSign, Let's Encryptなどがあります。
証明書には「この公開鍵はこのドメインのもの」という情報が含まれており、CAがそれにデジタル署名をします。
ただし、実際にはルートCAが直接サーバ証明書を発行するのではなく、間に中間CAを置くのが一般的です。
ルートCA
ルートCAは、証明書チェーンにおける「信頼の起点」です。
今回の例では、DigiCertのルートCAがこれにあたります。
ルートCAはルート証明書を持っています。PCやスマホ、ブラウザには、これら信頼するルート証明書が予め登録されており、それらをTrust Storeと呼びます。
ルート証明書は、自分の秘密鍵で署名されている自己署名証明書であり、他に上位のCAによる署名が行われずとも信頼される特別な証明書です。
ルートCAの秘密鍵が漏洩すると、そのCAを起点とした証明書の信頼に大きな影響が出るため、直接ルートCAがサーバ証明書を発行せず(=ルートCAの秘密鍵で署名をせず)、通常はその秘密鍵で署名された中間CAにより証明書は発行されます。ルートCAの秘密鍵はオフライン環境で厳重に管理されており、滅多に使われることはないようです。
中間CA
中間CAは、ルートCAとサーバ証明書の間に存在するCAです。
中間CAも自身の鍵ペア(秘密鍵・公開鍵)を持っています。
この中間CA公開鍵を含む証明書が中間証明書で、ルートCAの秘密鍵で署名されています。
証明書チェーン
ここまでで、
- ルート証明書
- 中間証明書
- サーバ証明書
という3種類の証明書が登場しました。これらは独立しているのではなく、デジタル署名によって信頼関係が繋がっています。
┌─────────────────┐
│ ルート証明書
│
│ ・ルートCA公開鍵
└─────────────────┘
│
│ この公開鍵で
│ 中間証明書の署名を検証できる
▼
┌────────────────┐
│ 中間証明書
│
│ ・中間CA公開鍵
│ ・ルートCAによる署名
└────────────────┘
│
│ この公開鍵で
│ サーバ証明書の署名を検証できる
▼
┌────────────────┐
│ サーバ証明書(example.com)
│
│ ・サーバ公開鍵
│ ・中間CAによる署名
└────────────────┘このように、上位CAによる信頼の連鎖構造を証明書チェーンと呼びます。信頼の起点として選ばれたルートCAの成り立ちについては、また別の機会にまとめてみます。
PKI (公開鍵基盤)
ここまでで説明してきた、
- 公開鍵・秘密鍵
- デジタル署名
- CAによる証明書の発行
- ルートCA・中間CA
- Trust Store
- 証明書チェーンによる検証
といった仕組みは、PKI (Public Key Infrastructure / 公開鍵基盤)と呼ばれる仕組みの一部です。
公開鍵暗号では、公開鍵は誰でも作れます。例えばあるサーバから、これがexample.comの公開鍵です。と公開鍵だけ渡されても、ブラウザはその公開鍵を信頼する手段がありません。そこで、PKIでは信頼できる第三者であるCAが、
この公開鍵はexample.comのものだと確認しました
という情報をサーバ証明書として発行し、CAの秘密鍵で署名します。そうすることで、ブラウザは証明書チェーンを辿って検証し、受け取った公開鍵の信頼性を判断できます。
PKIは、この公開鍵は「本当に相手のものなのか?」を証明書とCAを使って確認できるようにする仕組み
ということができると思います。
証明書発行までの流れ
では、この証明書チェーンの一番下のexample.comのサーバ証明書はどのように発行されるのでしょうか。
太郎さんがDigiCertへ証明書を申請して、サーバ証明書を取得するまでを見ていきます。
1. 太郎さんが鍵ペアを用意する
まず、example.com用の秘密鍵・公開鍵を作ります。例えばOpenSSLを使う場合、次のように生成します。
# 秘密鍵を生成
openssl genrsa -out example.com.key 2048
> example.com.key # 秘密鍵
# 秘密鍵から公開鍵を取り出す
openssl pkey -in example.com.key -pubout -out example.com.pub
> example.com.pub # 公開鍵⚠️秘密鍵は太郎さん側で厳重に保管します
2. CSRを作成して証明書を申請する
DigiCertに対し、「example.comのこの公開鍵に対する証明書を発行してください」とリクエストします。この時使われるのがCSR (Certificate Signing Request)です。以下のような情報がCSRに含まれます。
example.com.csr
┌───────────────┐
│ 証明書に入れてほしい情報
│
│ ・ドメイン名など
│
│ ・Public Key
│ 太郎さんの公開鍵
│
│ ・Signature
│ 太郎さんの秘密鍵で署名
└───────────────┘CSRの検証(所持証明)
CSRは、太郎さんの秘密鍵で署名されています。CAは、CSR内の公開鍵を使ってその署名を検証することで「このCSRを作った人は、ここに含まれてる公開鍵に対応する秘密鍵を確かに持ってるね」と確認できます。
署名の検証とは
太郎さんは、CSR全体のハッシュ値を秘密鍵で署名します。CAは、その署名を公開鍵で検証し、元のハッシュ値を取り出します。そしてCSR全体のハッシュ値と比べることで、正しいかどうかがわかります。ですので、CAはどのハッシュ関数を使ったのか知る必要があるので、CSRにはハッシュ関数情報(SHA-256、といった情報)も含まれています。
3. ドメイン認証
CSRが検証できても、「この人が本当にexample.comを管理しているのか?」まではわかりません。そのため、DigiCertはドメインの管理権を確認します(ドメイン認証)。
例えばHTTPを利用した方法では、DigiCertから指定された値を含むファイルを、example.comサーバ上の指定された場所に配置します。
すると、CAはhttp://example.com/アップロードしたファイルパス へアクセスし「確かにドメインの所有者だね」と確認します。この他にも、DNSのTXTレコード/CNAMEレコードを利用した方法、メールを利用した確認方法があります。
4. 中間CAがサーバ証明書を発行する
ドメインの確認ができたら、DigiCertの中間CAがexample.comのサーバ証明書を発行します。
サーバ証明書は以下のような情報を持ちます。
Subject
example.com
Public Key
太郎さんのサーバ公開鍵
Issuer (発行者)
DigiCert中間CA
Validity
有効期間
Signature
DigiCert中間CA秘密鍵で作られた署名重要なのは、DigiCert中間CAによる署名があることです。これにより「太郎さんのサーバ公開鍵は信用できますよ」というになります。
5. 太郎さんが証明書を受け取る
最終的に太郎さん側は、作成されたサーバ証明書と、中間証明書を受け取ります。
この中間証明書は、太郎さん専用に作られたものではなく、DigiCert側で既に存在している中間CAの証明書です。
example.comのWebサーバでは、TLS接続時にサーバ証明書と中間証明書をブラウザへ提示できるように設定します。
以上が、サーバ証明書発行の流れです。
ブラウザはサーバ証明書をどう検証するのか
- TLS接続時に、ブラウザはサーバ証明書と中間証明書を受け取る。
- サーバ証明書の署名を、中間証明書の公開鍵で検証する
- 中間証明書の署名を、TrustStoreのルート証明書で検証する
これによってブラウザは、サーバ証明書に含まれる公開鍵が、信頼できるCAによってexample.comに対して認証されたものであることを確認できます。
おわりに
今回は、TLSで使われるサーバ証明書がどのように発行され、ブラウザがなぜその証明書を信頼できるのかを整理しました。
公開鍵だけでは、「その公開鍵が本当に接続したい相手のものなのか」は判断できません。
そこで、CAによる証明書の発行と、Trust Storeを起点とした証明書チェーンによって公開鍵とドメインの関係を検証できるようにした仕組みがPKIです。
以前の記事ではTLSハンドシェイクについて調べましたが、今回PKIや証明書の仕組みを整理したことで、TLSハンドシェイク中にブラウザが「なぜサーバから送られてきた証明書を信用できるのか」が理解できました。