認証局(CA)とデジタル署名・証明書の発行フロー
このドキュメントでは、TLS/SSL通信の信頼性を支える「認証局(CA)」「デジタル署名」の仕組みと、実際にサーバー証明書が発行・検証されるまでのフローをまとめます。
1. 認証局 (CA: Certificate Authority) とは
インターネット上で「このサーバー(またはクライアント)は本物である」という身元を保証する、信頼された第三者機関のことです。
- パブリックCA: Let’s Encrypt や DigiCert など、厳格な審査基準を持つ公的機関。世界中のOSやブラウザ(Windows, Mac, iOS, Chromeなど)には、購入した時点でこれらの「ルートCA証明書(CAの公開鍵)」が約150〜200個ほどあらかじめインストールされています。
- プライベートCA (オレオレCA): 社内ネットワークや開発用など、特定の組織内だけで独自に立てたCA。パブリックな信頼はないため、利用するOSやプログラムの「信頼するリスト(Trust Store)」に手動で追加する必要があります。
2. デジタル署名とは
証明書が「絶対にそのCAが発行した本物であること」および「途中で改ざんされていないこと」を数学的に証明する仕組みです。現実世界のハンコやサインにあたりますが、実態は**「CAの秘密鍵による暗号化データ」**です。
署名(ハンコを押す)の仕組み
- 証明書に記載するデータ(ドメイン名、サーバーの公開鍵、有効期限など)から、一定の長さのハッシュ値(データの指紋)を計算します。
- そのハッシュ値を、CAが厳重に管理している「CAの秘密鍵」で暗号化します。これが「デジタル署名」です。
検証(ハンコを確認する)の仕組み
「CAの秘密鍵」で暗号化されたデータは、対となる「CAの公開鍵」でしか解読できません。 クライアントは、OSに最初から入っている「CAの公開鍵」を使ってデジタル署名を復号します。復号に成功し、計算したハッシュ値が一致すれば、「間違いなくそのCAが署名したものであり、1文字も改ざんされていない」ことが証明されます。
3. 証明書の発行から検証までのフロー
Webサーバーの運営者が証明書を取得し、クライアントがそれを検証するまでの流れは以下の通りです。
フェーズ1:証明書の発行依頼(CSRの作成)
サーバー運営者は、まず自分の鍵ペアを作成し、CAに身元保証を依頼します。
- 秘密鍵の作成: サーバー上で自分専用の「秘密鍵(例:
server.key)」を生成します。これは絶対に外部に漏らしてはいけません。 - CSRの作成: 生成した秘密鍵を使い、「私のドメイン名は example.com で、公開鍵はこれです。証明書を発行してください」という証明書署名要求 (CSR: Certificate Signing Request) を作成します。
- CAへ提出: 作成した CSR を CA(Let’s Encryptなど)に送信します。
フェーズ2:CAによる審査と署名(証明書の発行)
CAは依頼主が本当にそのドメインの所有者であるかを確認し、証明書を発行します。
- 身元審査: CAは、ドメインの所有権確認(DNSレコードの確認や指定URLへのファイル配置など)を行います。
- デジタル署名の付与: 審査を通過すると、CAは CSR の情報をもとにハッシュ値を計算し、それを**「CAの秘密鍵」**で暗号化してデジタル署名を作成します。
- 証明書の完成: サーバーの情報とデジタル署名を合体させたものが**「サーバー証明書(例:
server.crt)」**となります。これをサーバー運営者に返却します。
フェーズ3:通信時の証明書の提示と検証
ユーザー(クライアント)がサイトにアクセスした際の検証フローです。
- 証明書の提示: クライアントがサーバーにアクセス(TLSハンドシェイクの
ClientHello)すると、サーバーはserver.crtを返します。 - 信頼のチェーン確認: クライアントは、送られてきた証明書の「発行者(Issuer)」を確認します。
- 署名の検証: クライアントのOSに入っている**「CAの公開鍵」**を使って証明書のデジタル署名を復号・検証します。
- 通信の開始: 検証が成功(改ざんがなく、信頼できるCAによる発行だと確認できた)すれば、証明書に含まれる「サーバーの公開鍵」を使って暗号化通信の土台作りへ進みます。
4. OpenSSLコマンドによる実装例
上記のフローを、ローカル開発環境で openssl コマンドを使って再現する手順です(本リポジトリの証明書生成スクリプトが行っている処理とほぼ同じです)。
事前準備:CA(認証局)自身の設立
まずは署名を行う「大元のCA」を作り、CA自身の秘密鍵と公開鍵(ルート証明書)を用意します。
# 1. CAの秘密鍵を作成
openssl genrsa -out ca.key 2048
# 2. CAのルート証明書を作成(自分自身で署名=自己署名)
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt -subj "/CN=My Root CA"フェーズ1:証明書の発行依頼(サーバー運営者)
サーバー運営者が自分の鍵を作り、CAに「証明書を作ってください」とお願いする(CSRを作る)フェーズです。
# 1. サーバーの秘密鍵を作成
openssl genrsa -out server.key 2048
# 2. CSR(証明書署名要求)を作成
openssl req -new -key server.key -out server.csr -subj "/CN=localhost"フェーズ2:CAによる審査と署名(CA)
CAが受け取ったCSR(server.csr)に対して、CAの秘密鍵(ca.key)を使ってハンコを押し、サーバー証明書を発行します。
# CAがCSRに署名し、サーバー証明書(server.crt)を発行する
openssl x509 -req -in server.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 365 -sha256フェーズ3:通信時の証明書の提示と検証(クライアント)
クライアントが、サーバーから渡された証明書を、手元にあるCAの公開鍵を使って検証するフェーズです。
# CAの公開鍵(ca.crt)を使って、server.crt が本物か検証する
openssl verify -CAfile ca.crt server.crt成功した場合の出力:
server.crt: OK