【図解】PKIとは?証明書・認証局・チェーン・失効(CRL・OCSP)のしくみを初心者向けに解説

TLS の記事では、サーバが本物かどうかを、証明書が「信頼する CA までつながるか」で確かめました。では、その CA とは何で、つながりはどう作られ、使えなくなった証明書はどう止めるのか。この記事では、証明書のしくみ全体である PKI(公開鍵基盤)を、RFC と Microsoft のドキュメントで確かめながら、テスト用の環境で OpenSSL を使ってルート CA から実際に作り、失効まで動かした結果と一緒に一歩ずつ図にしました。

この記事でわかること
  1. PKI は「信頼できる発行元(CA)が、名前と公開鍵の組み合わせを保証する」しくみ
  2. 証明書の中身(発行者・主体・有効期間・公開鍵・拡張・CA の署名)
  3. ルート・中間・サーバの証明書チェーンと、クライアントが確かめること
  4. 失効のしくみ(CRL と OCSP)と、有効期間の短縮・更新の自動化
  5. OpenSSL で CA を作り、発行・検証・失効を実際に試す方法

まずはたとえで:パスポート

海外に行くとき、パスポートを見せて入国審査を受けます。パスポートは国が発行したもので、名前・写真・番号・有効期限が書かれ、国の印が押されています。入国審査では、信じている国の印か、期限内か、写真の本人か、無効になったパスポートのリストに載っていないかを確かめます。

国 = 認証局(CA)国の印(秘密鍵)は国の中にしまってあるどの国を信じるかは審査する側が決めているパスポート = 証明書名前主体・SAN写真公開鍵番号シリアル番号有効期限有効期間発行した国発行者国の印CA の署名入国審査 = 検証信じている国の印か期限内か写真の本人か無効のリストにないか(失効の確認)PKI は「信頼できる発行元が、名前と公開鍵の組み合わせを保証する」しくみ
図1 パスポートで見る PKI

PKI(Public Key Infrastructure、公開鍵基盤)は、これをデジタルの世界で行うしくみです。国にあたるのが CA(Certificate Authority、認証局)、パスポートにあたるのが証明書、写真にあたるのが公開鍵です。RFC 5280 は、公開鍵と持ち主の結びつきを、信頼される CA が証明書に署名することで示す、と説明しています。どの CA を信じるかは、パスポートと同じく、確かめる側があらかじめ決めておきます。

使う場面

証明書は TLS のサーバ証明書だけでなく、いろいろな場面で使われています。Microsoft の AD CS(Active Directory 証明書サービス)のドキュメントも、証明書の確認ができないと、VPN の接続、スマートカードでのサインイン、メールの署名の確認などが失敗すると書いています。

HTTPS のサーバ証明書サーバが本物かを示す(前の記事)クライアント証明書mTLS で利用者や機器を示す(次の記事)VPN の接続機器や利用者を証明書で確かめるスマートカードのサインインカードの中の鍵と証明書メールの署名送り主と、書き換えがないことを示すSAML・コードの署名署名した相手を証明書で確かめるどれも同じしくみ:CA が「この公開鍵は、この名前のもの」と署名し、受け取った側が、信頼する CA までたどって確かめる証明書は TLS だけのものではない。署名や認証の多くが同じ PKI の上に乗っている
図2 証明書を使う場面

このシリーズでは、SAML のアサーションの署名を証明書で確かめる話も出てきました。次の記事で扱う mTLS では、クライアントも証明書で自分を示します。どれも、ここで見る PKI のしくみの上に乗っています。

PKI の基本の形

証明書の中身

証明書の形式は X.509 で、インターネットで使う形は RFC 5280 で決まっています。証明書は「署名される中身(tbsCertificate)」「署名のアルゴリズム」「署名の値」の3つでできています。中身には、シリアル番号、発行者、有効期間、主体(持ち主)、公開鍵と、v3 で加わった拡張が入ります。図は、この記事の STEP 3 で実際に発行したサーバ証明書の値です。

証明書(X.509 v3)= 署名される中身 + CA の署名署名される中身(tbsCertificate)シリアル番号1000CA の中で1枚ずつ違う番号発行者CN = Demo Issuing CA署名した CA の名前有効期間2026-11-02 〜 2027-01-31notBefore・notAfter主体CN = api.example.test持ち主の名前公開鍵EC P-256持ち主の公開鍵拡張(v3 の拡張)基本制約CA:FALSECA ではない(証明書を発行できない)用途Digital Signature・serverAuth署名に使う・サーバ認証用SANDNS:api.example.test接続先の名前と比べるCRL 配布点・AIAhttp://pki… ・OCSP失効情報と CA 証明書の場所CA の署名(signatureAlgorithm・signatureValue)上の中身全体に、発行者(中間 CA)の秘密鍵で署名。1文字でも変えると検証に失敗する証明書は「名前と公開鍵と条件」に、CA が印を押したもの
図3 証明書(X.509 v3)の中身
拡張意味
基本制約(basicConstraints)CA:TRUE なら CA の証明書。CA:FALSE の証明書の公開鍵で、ほかの証明書の署名を確かめてはいけない。pathlen は、この後に続いてよい中間 CA の数
鍵の用途(keyUsage)CA なら証明書への署名(keyCertSign)と CRL への署名(cRLSign)。サーバ証明書なら署名(digitalSignature)など
拡張鍵用途(EKU)サーバ認証(serverAuth)、クライアント認証(clientAuth)など、何に使う証明書か
SAN(subjectAltName)持ち主の名前。TLS では接続先の名前と比べる
CRL 配布点(CDP)失効リスト(CRL)を取りに行く場所
AIA発行した CA の証明書の場所や、OCSP(失効の問い合わせ先)の場所

証明書チェーン:ルート・中間・サーバ

多くの PKI では、CA を2階層以上に分けます。いちばん上のルート CA は、自分で自分に署名した証明書(自己署名証明書)を持ちます。RFC 5280 は、自己署名証明書が「証明書のつながりを始めるための公開鍵」を伝えるために使われる、としています。ルート CA は中間 CA(発行 CA)の証明書に署名し、中間 CA がサーバなどの証明書を発行します。

ルート証明書CN = Demo Root CA発行者 = 主体(自己署名)CA:TRUE中間証明書CN = Demo Issuing CA発行者:Demo Root CACA:TRUE, pathlen:0サーバ証明書CN = api.example.test発行者:Demo Issuing CACA:FALSE・SANルートの秘密鍵で署名中間の秘密鍵で署名サーバが TLS で送るサーバ証明書+中間証明書クライアントが持っている信頼済みストアに入っている鍵はふだんオフライン下から上へ、発行者の公開鍵で署名をたどり、信頼するルートに着けば OK
図4 証明書チェーン

ルートの秘密鍵が漏れると、その下のすべての証明書が信頼できなくなります。そのため Microsoft は、本番の AD CS では、スタンドアロンのルート CA で発行 CA に署名したら、ルート CA をオフラインにすることを推奨しています。ふだんの発行は中間 CA が行い、ルートは中間 CA の証明書を作り直すときなどにだけ使います。

ルート証明書が本物かどうかは、証明書だけでは確かめられません。自己署名なので、だれでも同じ名前のルート証明書を作れるからです。Microsoft の Cloud PKI の説明も、ルート証明書を信頼するには、信頼済みのルートストアに入れるしかない、としています。OS やブラウザには、あらかじめ公的な CA のルート証明書が入っていて、社内の CA なら、管理者が社内の PC に配ります。

誰が何を持つか

ルート CA中間 CA(発行 CA)サーバクライアントルートの秘密鍵オフライン・HSM などルート証明書自己署名。配られるルートの CRL中間を失効させるとき中間の秘密鍵証明書と CRL に署名中間証明書ルートの署名つき発行の記録シリアル・状態CRL・OCSP失効情報を出すサーバの秘密鍵サーバの外に出さないサーバ証明書中間の署名つき中間証明書一緒に送る信頼するルート信頼済みストア確かめるルール期限・名前・用途失効情報CRL を取る・OCSP秘密鍵は3か所(ルート・中間・サーバ)。どれも持ち主の外に出さない
図5 誰が何を持つか

秘密鍵は、ルート CA・中間 CA・サーバの3か所にあります。どれも持ち主の外に出してはいけませんが、漏れたときの影響が大きいのはルート、次に中間です。相手に渡すのは、いつも公開鍵の入った証明書だけです。

全体の流れ

準備:CA の階層を作る

まず、ルート CA と中間 CA を作り、ルート証明書をクライアントに配ります。

管理者ルート CA中間 CAクライアント① ルート CA で操作鍵ペアと自己署名の証明書② ルート証明書を配る信頼済みストアに入れる③ 中間 CA で操作:鍵ペアと CSR④ CSR をルートへオフラインならファイルで運ぶ⑤ 確かめて署名ルートの秘密鍵でCA:TRUE, pathlen:0⑥ 中間証明書⑦ オフラインにするふだんは使わない⑧ 中間 CA で操作:CRL 配布点と AIA証明書を発行する前に決める⑨ 発行の準備ができた中間の鍵で署名するルートは信頼の起点として配り、ふだんの発行は中間 CA に任せる
図6 準備の流れ(①〜⑨)
手順誰が・どこで何をするか鍵(物)はどうなるか・使う鍵
①管理者・ルート CA で操作鍵ペアと自己署名の証明書を作るルートの秘密鍵はルート CA の中だけ。証明書は CA:TRUE
②ルート CA → クライアントルート証明書を配るクライアントの信頼済みストアに入る(信頼の起点)
③管理者・中間 CA で操作鍵ペアと CSR を作る中間の秘密鍵は中間 CA の中だけ
④中間 CA → ルート CACSR を渡すルートがオフラインなら、ファイルで運ぶ
⑤ルート CA確かめて署名するルートの秘密鍵で署名。CA:TRUE, pathlen:0 を付ける
⑥ルート CA → 中間 CA中間証明書を渡す中間 CA が「ルートに認められた CA」になる
⑦ルート CAオフラインにするルートの秘密鍵をふだんは使わない
⑧管理者・中間 CA で操作CRL 配布点と AIA を決める発行する証明書に入る。あとで変えても、発行済みの証明書は古いまま
⑨中間 CA発行の準備ができる中間の秘密鍵で証明書と CRL に署名できる

CSR(Certificate Signing Request、証明書の申請書)は PKCS #10(RFC 2986)で決まっていて、名前と公開鍵などを入れ、申請者自身の秘密鍵で署名したものです。秘密鍵そのものは入っていません。⑧について Microsoft は、CA を作ったら、証明書を発行する前に AIA と CDP を決めるよう勧めています。URL を変えても、変える前に発行した証明書は古い場所を指したままだからです。

発行と利用:サーバ証明書を発行して使う

準備ができたら、サーバの証明書を発行し、クライアントがそれを確かめるところまでを見ます。

サーバ中間 CAクライアント失効情報(CRL・OCSP)発行(⑩〜⑯)使う(⑰〜㉒)⑩ 鍵ペアサーバで操作⑪ CSR名前・公開鍵⑫ CSR を送る秘密鍵は送らない⑬ 申請を確かめるその名前を使ってよいか⑭ 署名して発行中間の秘密鍵で発行の記録を残す⑮ サーバ証明書⑯ 設定する+中間証明書⑰ TLS で接続⑱ サーバ証明書+中間証明書⑲ チェーンをたどる署名・期限・CA:TRUE名前(SAN)・用途⑳ 失効を確かめるCRL を取る/OCSP で聞く㉑ 失効していないgood㉒ 信頼して通信を続けるCA は「名前と公開鍵」に署名し、クライアントはそれをたどって確かめる
図7 サーバ証明書の発行と利用(⑩〜㉒)
手順誰が・どこで何をするか鍵(物)はどうなるか・使う鍵
⑩サーバで操作鍵ペアを作るサーバの秘密鍵はサーバの中だけ
⑪サーバで操作CSR を作る名前(SAN)と公開鍵を入れ、サーバの秘密鍵で署名
⑫サーバ → 中間 CACSR を送る秘密鍵は送らない
⑬中間 CA申請を確かめるその名前を使ってよい相手か。公的 CA はドメインの管理を確かめる
⑭中間 CA署名して発行する中間の秘密鍵で署名。シリアル番号と状態を記録する
⑮中間 CA → サーバサーバ証明書を渡す証明書は公開の情報
⑯サーバで操作証明書と中間証明書を設定する秘密鍵と証明書の組み合わせを設定する
⑰クライアント → サーバTLS で接続する―
⑱サーバ → クライアントサーバ証明書と中間証明書を送るルート証明書は送らない(クライアントが持っている)
⑲クライアントチェーンをたどる中間の公開鍵でサーバ証明書の署名を、ルートの公開鍵で中間証明書の署名を確かめる
⑳クライアント → 失効情報失効を確かめるCRL 配布点から CRL を取るか、OCSP で聞く
㉑失効情報 → クライアント失効していないと答えるCRL も OCSP の応答も、CA などの署名つき
㉒クライアント信頼して通信を続けるTLS のハンドシェイクを続ける

⑬の確かめ方は、CA によって違います。社内の CA なら申請者が社内の人や機器かを、公的な CA ならそのドメインを管理しているかを確かめます。公的な CA で使われている ACME(RFC 8555)は、この確認と発行を自動化するプロトコルで、CA が HTTP(http-01)や DNS(dns-01)を通して、申請者がドメインを管理していることを確かめます。

クライアントが確かめること

⑲⑳でクライアントが確かめることを、証明書ごとに並べると次のようになります。

ルート証明書信頼済みストアにあるここが起点(トラストアンカー)中間証明書ルートの公開鍵で署名期限CA:TRUEpathlen失効していないサーバ証明書中間の公開鍵で署名期限用途(EKU)名前(SAN)失効していないどれか1つでも合わなければ、チェーン全体を信頼しない。名前(SAN)は接続先と比べるので、サーバ証明書だけで確かめる。CA:TRUE と pathlen は「CA が証明書を発行してよいか」を表す1枚ずつ「署名・期限・役割・失効」を確かめ、サーバ証明書では名前と用途も見る
図8 チェーンで確かめること

大事なのは、1枚ずつ「その証明書が CA として署名してよい立場か」を見ることです。たとえば、CA:FALSE のサーバ証明書の鍵で別の証明書に署名しても、その証明書は信頼されません。RFC 5280 は、cA が立っていない証明書の公開鍵で、証明書の署名を確かめてはいけないとしています。

失効:期限の前に「もう信じないで」と伝える

CRL と OCSP

秘密鍵が漏れたかもしれないとき、組織から外れた人の証明書を止めたいときなどは、期限を待たずに証明書を使えなくする必要があります。これが失効(revocation)です。失効を伝える方法には、CRL と OCSP の2つがあります。

CRL(失効リスト)CA が、失効した証明書のシリアル番号の一覧に署名して、定期的に公開するシリアル 1000・Key Compromise次の更新:Next Update中間 CA の署名場所は証明書の CRL 配布点(CDP)まとめて取れる。取り直すまでは古いまま公的 CA では CRL が必須(SC063)OCSP(1枚ずつ問い合わせ)クライアントがレスポンダに「この証明書は?」と聞くgood失効していないrevoked失効しているunknownこのレスポンダは知らない応答はレスポンダの署名つき聞いた先に、接続先が分かってしまう公的 CA では任意。止めた CA もある失効は、すぐには全員に届かない。クライアントが新しい CRL や OCSP の応答を取るまでは、失効した証明書を使えてしまうことがある期限より前に「もう信じないで」と伝えるのが失効。CRL と OCSP の2つの方法がある
図9 失効を伝える2つの方法
  • CRL(Certificate Revocation List):RFC 5280 は、CRL を「失効した証明書を示す、時刻つきで CA などが署名したリスト」と説明しています。新しい CRL は、1時間ごと・1日ごと・1週間ごとなど、決まった間隔で出されます。
  • OCSP(Online Certificate Status Protocol):RFC 6960 で決まっている、1枚ずつ状態を聞く方法です。答えは good(失効していない)、revoked(失効している)、unknown(このレスポンダはその証明書を知らない)の3つで、確定した応答には必ず署名が付きます。

失効させる流れ

管理者中間 CA失効情報(CRL・OCSP)クライアント❶ 漏えいに気づく❷ 中間 CA で操作:失効理由 keyCompromise❸ 記録を「失効」にシリアル 1000❹ 新しい CRL を公開OCSP にも反映❺ CRL を取る/OCSP で聞く❻ revoked❼ 接続しない❹より前の CRL を持っているクライアントは、次に取り直すまで失効に気づかない失効は「CA に記録して、公開して、クライアントが取る」まででひと続き
図10 証明書を失効させる流れ(❶〜❼)
項目最初の図(図7)この図(失効)
CA の記録有効(⑭)失効。理由も記録する(❸)
失効情報載っていない新しい CRL に載り、OCSP も revoked と答える(❹)
クライアントの判断信頼して続ける(㉒)接続しない(❼)
証明書そのもの変わらない変わらない。期限もそのまま

Microsoft の AD CS のドキュメントは、失効はすべての相手に同時に届くわけではなく、相手が新しい CRL や OCSP の応答を取るまでは、失効した証明書が使えてしまうことがある、と注意しています。CA に記録するだけでなく、新しい CRL を公開して、取りに行ける場所に置くところまでが失効の作業です。

公的 CA の OCSP の今

公的な証明書の決まり(CA/Browser Forum の Baseline Requirements)は、改訂(SC063)で OCSP を任意にし、CRL を必須にしました。Let’s Encrypt は、OCSP では問い合わせ先の CA に利用者の見ているサイトが分かってしまうというプライバシーの理由で、2025年5月7日に証明書から OCSP の URL を外し、2025年8月6日に OCSP のレスポンダを止めて、失効情報を CRL だけで出すようにしました。社内の CA(AD CS など)では、引き続き OCSP(オンラインレスポンダ)を使えます。

有効期間は短くなっていく

公的な TLS サーバ証明書は、有効期間そのものを短くする方向に進んでいます。CA/Browser Forum の Baseline Requirements(SC081 による改訂)は、最長の有効期間を段階的に短くすると決めています。

398日最長の有効期間〜2026/3/14200日最長の有効期間2026/3/15〜100日最長の有効期間2027/3/15〜47日最長の有効期間2029/3/15〜▲ 今(2026年11月)はこの期間公的に信頼される TLS サーバ証明書の決まり(CA/Browser Forum の Baseline Requirements、SC081)社内 CA の証明書は、組織で決める。ただし短いほど、漏えいしたときの影響が小さい人の手で更新するのは難しくなるので、ACME や Key Vault などで自動にする公的な証明書は、2029年には47日まで短くなる。更新の自動化が前提
図11 公的な TLS サーバ証明書の最長の有効期間

2026年11月の今は、最長200日の期間です。2029年には47日になり、人の手で更新するのは現実的ではなくなります。ACME や、後で見る Azure Key Vault の自動更新のように、更新を自動にすることが前提になります。社内の CA の証明書はこの決まりの対象ではありませんが、短いほど漏れたときの影響が小さいことは同じです。

試してみる(OpenSSL で CA を作る)

ここからは、テスト用の環境で OpenSSL 3.0.13 を使い、ルート CA・中間 CA・サーバ証明書を作って、検証と失効を試した結果を見ていきます。名前は試験用のドメイン(example.test)にしています。本番の CA は、この手順ではなく、AD CS や公的な CA のサービスで作ります。

ルート CA を作る(図6の①)

ルートの鍵ペアと、自己署名のルート証明書を作ります。-addext で、CA であること(CA:TRUE)と、証明書と CRL に署名する用途を付けます。

ルート CA を作る(ルート CA で操作、図6の①)

openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout root.key -out root.crt -days 365 -subj "/CN=Demo Root CA" -addext "basicConstraints=critical,CA:TRUE" -addext "keyUsage=critical,keyCertSign,cRLSign"

ルート証明書の中身を見る

openssl x509 -in root.crt -noout -subject -issuer -ext basicConstraints,keyUsage
subject=CN = Demo Root CA
issuer=CN = Demo Root CA
X509v3 Basic Constraints: critical
    CA:TRUE
X509v3 Key Usage: critical
    Certificate Sign, CRL Sign
openssl req -x509 …root.keyroot.crt秘密鍵(外に出さない)ルート証明書(配る)root.crt の中身で見るところsubjectCN = Demo Root CA主体issuerCN = Demo Root CA発行者 = 主体 → 自己署名CA:TRUEcriticalCA として証明書を発行できるKey UsageCertificate Sign, CRL Sign証明書と CRL に署名するルートは自分で自分に署名する。信頼されるかどうかは、配った先が決める
図12 STEP 1 でできたファイルと、ルート証明書で見るところ

発行者(issuer)と主体(subject)が同じなのが、自己署名の証明書です。このルート証明書 root.crt を、クライアントに「信頼する CA」として渡します(図6の②)。

中間 CA を作る(図6の③〜⑥)

中間 CA に付ける拡張をファイルに書きます。pathlen:0 で、この中間 CA の下には CA を置けないようにします。

inter.ext の中身

basicConstraints=critical,CA:TRUE,pathlen:0
keyUsage=critical,keyCertSign,cRLSign
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid

中間 CA の鍵ペアと CSR を作り、ルートの鍵で署名します。

中間 CA の鍵と CSR を作り、ルートで署名する(図6の③〜⑥)

openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout inter.key -out inter.csr -subj "/CN=Demo Issuing CA"
openssl x509 -req -in inter.csr -CA root.crt -CAkey root.key -CAcreateserial -out inter.crt -days 180 -extfile inter.ext
Certificate request self-signature ok
subject=CN = Demo Issuing CA

中間証明書の中身を見る

subject=CN = Demo Issuing CA
issuer=CN = Demo Root CA
X509v3 Basic Constraints: critical
    CA:TRUE, pathlen:0
X509v3 Key Usage: critical
    Certificate Sign, CRL Sign
inter.keyinter.csr中間 CA の側openssl x509 -reqルートの秘密鍵(root.key)で署名拡張は inter.ext から:CA:TRUE, pathlen:0inter.crt中間証明書pathlen:0 の意味この中間 CA の下には、もう CA を置けない。発行できるのはサーバなどの証明書(CA:FALSE)だけpathlen は「この後に続いてよい中間 CA の数」。0 なら、下に CA が来ると検証に失敗する中間 CA の証明書は、ルートが「CA としてここまで発行してよい」と決めて署名したもの
図13 STEP 2 で中間 CA を作る

サーバ証明書を発行する(図7の⑩〜⑮)

中間 CA が発行の記録を残せるように、openssl ca を使います。設定ファイルに、記録のファイルや、サーバ証明書に付ける拡張(server_ext)を書いておきます。client_ext と ocsp_ext は、STEP 6 と「うまくいかないとき」で使います。

ca.cnf の中身

[ ca ]
default_ca = issuing

[ issuing ]
database         = ./index.txt
new_certs_dir    = ./newcerts
certificate      = ./inter.crt
private_key      = ./inter.key
serial           = ./serial
crlnumber        = ./crlnumber
default_md       = sha256
default_days     = 90
default_crl_days = 7
policy           = pol

[ pol ]
commonName = supplied

[ server_ext ]
basicConstraints      = critical,CA:FALSE
keyUsage              = critical,digitalSignature
extendedKeyUsage      = serverAuth
subjectAltName        = DNS:api.example.test
crlDistributionPoints = URI:http://pki.example.test/issuing.crl
authorityInfoAccess   = OCSP;URI:http://localhost:8888,caIssuers;URI:http://pki.example.test/issuing.crt

[ client_ext ]
basicConstraints      = critical,CA:FALSE
keyUsage              = critical,digitalSignature
extendedKeyUsage      = clientAuth
authorityInfoAccess   = OCSP;URI:http://localhost:8888

[ ocsp_ext ]
basicConstraints      = critical,CA:FALSE
keyUsage              = critical,digitalSignature
extendedKeyUsage      = critical,OCSPSigning

発行の記録に使うファイルを用意する

mkdir -p newcerts && touch index.txt && echo 1000 > serial && echo 1000 > crlnumber

サーバの鍵と CSR を作り、中間 CA で発行する(図7の⑩〜⑮)

openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout server.key -out server.csr -subj "/CN=api.example.test"
openssl ca -config ca.cnf -batch -extensions server_ext -in server.csr -out server.crt
Using configuration from ca.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'api.example.test'
Certificate is to be certified until Jan 31 06:06:38 2027 GMT (90 days)

Write out database with 1 new entries
Database updated

サーバ証明書の中身を見る

openssl x509 -in server.crt -noout -subject -issuer -serial -dates -ext basicConstraints,keyUsage,extendedKeyUsage,subjectAltName,crlDistributionPoints,authorityInfoAccess
subject=CN = api.example.test
issuer=CN = Demo Issuing CA
serial=1000
notBefore=Nov  2 06:06:38 2026 GMT
notAfter=Jan 31 06:06:38 2027 GMT
X509v3 Basic Constraints: critical
    CA:FALSE
X509v3 Key Usage: critical
    Digital Signature
X509v3 Extended Key Usage: 
    TLS Web Server Authentication
X509v3 Subject Alternative Name: 
    DNS:api.example.test
X509v3 CRL Distribution Points: 
    Full Name:
      URI:http://pki.example.test/issuing.crl
Authority Information Access: 
    OCSP - URI:http://localhost:8888
    CA Issuers - URI:http://pki.example.test/issuing.crt
server.csrサーバから届いた申請openssl ca(中間 CA)ca.cnf設定inter.crt・inter.key署名に使うindex.txt発行の記録(状態)serial次のシリアル番号newcerts/発行した証明書の控えserver.crtシリアル 1000server_ext で付けた拡張CA:FALSECA ではないserverAuthサーバ認証用DNS:api.example.test名前(SAN)CRL 配布点http://pki.example.test/issuing.crlAIA(OCSP)http://localhost:8888openssl ca は記録を残して発行する。だから、あとで失効させられる
図14 STEP 3 でサーバ証明書を発行する

シリアル番号 1000 の証明書ができ、index.txt に発行の記録が残りました。CRL 配布点と AIA に入っている URL は、クライアントが失効情報や中間証明書を取りに行く場所です(このテストでは、CRL 配布点の URL は使わず、CRL のファイルを直接渡します)。

チェーンを検証する(図7の⑲)

openssl verify で、信頼するルート(-CAfile)と、途中の中間証明書(-untrusted)を渡して確かめます。-untrusted は「信頼の起点にはしないが、つながりをたどるのに使う」という意味です。

中間証明書を渡して検証する

openssl verify -CAfile root.crt -untrusted inter.crt -show_chain server.crt
server.crt: OK
Chain:
depth=0: CN = api.example.test (untrusted)
depth=1: CN = Demo Issuing CA (untrusted)
depth=2: CN = Demo Root CA

中間証明書を渡さないと、ルートを持っていてもたどれません。

中間証明書を渡さずに検証する

openssl verify -CAfile root.crt server.crt
CN = api.example.test
error 20 at 0 depth lookup: unable to get local issuer certificate
error server.crt: verification failed
-untrusted inter.crt ありdepth=2: CN = Demo Root CAdepth=1: CN = Demo Issuing CAdepth=0: CN = api.example.testルートまでたどれたserver.crt: OK-untrusted なしDemo Root CA(持っている)Demo Issuing CA … ないdepth=0: CN = api.example.test発行者の証明書が見つからないerror 20 … local issuer中間証明書がないと、ルートを持っていてもたどれない
図15 STEP 4 でチェーンを検証する

サーバが中間証明書を送っていないと、クライアントでこれと同じことが起きます。サーバには、サーバ証明書と一緒に中間証明書も設定します(図7の⑯⑱)。

失効させて、CRL で確かめる(図10の❷〜❼)

まず、失効させる前の CRL を作り、-crl_check で失効も確かめます。

CRL を作って、失効も確かめる

openssl ca -config ca.cnf -gencrl -out issuing.crl
openssl verify -crl_check -CAfile root.crt -untrusted inter.crt -CRLfile issuing.crl server.crt
server.crt: OK

サーバの鍵が漏れたことにして、シリアル 1000 を理由 keyCompromise で失効させます。

失効させる(中間 CA で操作、図10の❷❸)

openssl ca -config ca.cnf -revoke newcerts/1000.pem -crl_reason keyCompromise
Using configuration from ca.cnf
Revoking Certificate 1000.
Database updated

CRL を作り直して中身を見る(図10の❹)

openssl ca -config ca.cnf -gencrl -out issuing.crl
openssl crl -in issuing.crl -noout -text
Certificate Revocation List (CRL):
        Version 2 (0x1)
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: CN = Demo Issuing CA
        Last Update: Nov  2 06:06:54 2026 GMT
        Next Update: Nov  9 06:06:54 2026 GMT
        CRL extensions:
            X509v3 CRL Number: 
                4097
Revoked Certificates:
    Serial Number: 1000
        Revocation Date: Nov  2 06:06:54 2026 GMT
        CRL entry extensions:
            X509v3 CRL Reason Code: 
                Key Compromise
    Signature Algorithm: ecdsa-with-SHA256
    Signature Value:
        30:45:02:20:04:d2:e5:f3:32:f4:2f:91:cd:5b:93:ae:7e:dc:
        b4:40:8b:a8:a9:b2:45:a3:48:95:ad:5e:c0:68:8a:dc:13:ff:
        02:21:00:9a:14:fb:da:1f:aa:ee:ef:c9:ab:e2:60:6f:54:0d:
        3b:f2:27:ae:63:ff:e8:2c:ae:45:9f:8e:dc:86:91:34:55

もう一度、失効も確かめる(図10の❺〜❼)

openssl verify -crl_check -CAfile root.crt -untrusted inter.crt -CRLfile issuing.crl server.crt
CN = api.example.test
error 23 at 0 depth lookup: certificate revoked
error server.crt: verification failed
失効させる前CRL:空のリストopenssl verify -crl_checkserver.crt: OK失効させた後(-revoke・-gencrl)CRL:シリアル 1000理由:Key Compromiseopenssl verify -crl_checkerror 23 … revoked証明書そのものは変わらない。変わったのは CA が出した CRL のほう
図16 STEP 5 で CRL を使って失効を確かめる

CRL には、失効した証明書のシリアル番号・日時・理由が載り、中間 CA が署名しています。Next Update は次の CRL を出す予定の日時で、設定ファイルの default_crl_days = 7 から7日後になっています。証明書そのものは何も変わっていません。変わったのは、CA が出した CRL のほうです。

OCSP で確かめる(図10の❺❻)

OCSP のレスポンダは、自分の応答に署名するための証明書(用途 OCSPSigning)を使います。比べるための「失効していない」証明書として、クライアント証明書も1枚発行しておきます。

クライアント証明書と、OCSP の署名用の証明書を発行する

openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout client.key -out client.csr -subj "/CN=app01"
openssl ca -config ca.cnf -batch -extensions client_ext -in client.csr -out client.crt
openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout ocsp.key -out ocsp.csr -subj "/CN=Demo OCSP Responder"
openssl ca -config ca.cnf -batch -extensions ocsp_ext -in ocsp.csr -out ocsp.crt

OpenSSL の ocsp コマンドで、発行の記録(index.txt)を見て答えるレスポンダを 8888 番で動かします。-nrequest 2 は、2回答えたら終わる指定です。

OCSP レスポンダを起動する(中間 CA の側で操作)

openssl ocsp -index index.txt -port 8888 -rsigner ocsp.crt -rkey ocsp.key -CA inter.crt -nrequest 2

失効していない証明書を問い合わせる

openssl ocsp -issuer inter.crt -cert client.crt -url http://localhost:8888 -CAfile root.crt -verify_other inter.crt
Response verify OK
client.crt: good
	This Update: Nov  2 06:07:00 2026 GMT

失効した証明書を問い合わせる

openssl ocsp -issuer inter.crt -cert server.crt -url http://localhost:8888 -CAfile root.crt -verify_other inter.crt
Response verify OK
server.crt: revoked
	This Update: Nov  2 06:07:00 2026 GMT
	Reason: keyCompromise
	Revocation Time: Nov  2 06:06:54 2026 GMT
openssl ocsp(問い合わせる側)OCSP レスポンダ(localhost:8888)index.txt を見て答えるocsp.crt・ocsp.key で署名client.crt は?シリアル 1001good署名つきの応答Response verify OK応答の署名を確かめたserver.crt は?シリアル 1000revokedkeyCompromise・失効した時刻OCSP は1枚ずつ聞き、署名つきの答えをもらう。答えも検証してから使う
図17 STEP 6 で OCSP を使って失効を確かめる

Response verify OK は、OCSP の応答の署名を確かめられたという意味です。OCSP の答えも、署名を確かめてから使います。

ここからは Microsoft の場合です

ここからは、Microsoft の環境で証明書を管理するしくみを見ます。クラウドでは Azure Key Vault で証明書と秘密鍵をまとめて管理し、社内では AD CS で自分たちの CA を動かすのが代表的な形です。

Azure Key Vault(証明書の管理)証明書ポリシー名前・鍵の種類・発行元・期限発行元が提携 CADigiCert・GlobalSign。自動で更新発行元がそれ以外の CACSR を出し、署名を戻す(マージ)自己署名自動で更新できるライフタイムアクション既定は寿命の80%で自動更新AD CS(社内の CA)2階層にするルート CA と発行 CA(中間)ルートはスタンドアロン発行 CA に署名したらオフラインAIA・CDP は先に決める変えても、発行済みは古いまま失効は CRL を公開して完了取り直すまでは使えてしまうOCSP はオンラインレスポンダcertutil -verify -urlfetch で確認クラウドでは Key Vault で期限と更新を、社内では AD CS で階層と失効を管理する
図18 Microsoft の環境での PKI
  • Azure Key Vault:証明書ポリシーに、証明書の名前、鍵の種類、発行元、有効期間、ライフタイムアクション(期限の何日前・寿命の何%で、自動更新するかメールで知らせるか)を書きます。発行元が提携している CA(DigiCert・GlobalSign)なら、Key Vault が更新まで自動で行います。それ以外の CA では、Key Vault が鍵ペアと CSR を作り、CA に署名してもらった証明書を「マージ」して戻します。ポータルで作る証明書の既定は有効期間12か月、寿命の80%で自動更新です。
  • 期限の監視:Key Vault は、期限の30日前に Microsoft.KeyVault.CertificateNearExpiry のイベントを Event Grid に出します。証明書の連絡先を登録しておくと、更新の前後や更新が必要なときにメールが届きます。
  • AD CS:本番では、スタンドアロンのルート CA と、ドメインに参加した発行 CA の2階層にし、発行 CA に署名したらルート CA はオフラインにするのが推奨です。AIA と CDP は証明書を発行する前に決めます。失効は、CRL を公開して相手が取れるようにするところまでが作業で、オンラインレスポンダ(OCSP)の動きは certutil -verify -urlfetch で確かめられます。

Key Vault で証明書の新しいバージョンを作る(Azure CLI)

az keyvault certificate create --vault-name "<vault-name>" -n "<certificate-name>" -p "$(az keyvault certificate get-default-policy)"

証明書のバージョンの一覧を見る(Azure CLI)

az keyvault certificate list-versions --vault-name "<vault-name>" -n "<certificate-name>"
有効期間の決まりについて

Microsoft の Key Vault のセキュリティのドキュメントも、公的な TLS 証明書の最長の有効期間が2026年3月から200日になり、2027年に100日、2029年に47日へ短くなる予定だとして、更新の自動化を勧めています。公的な証明書を Key Vault で手動で管理している場合は、早めに自動更新に移しておくと安心です。

よくある間違い

間違いどうするか
サーバにサーバ証明書だけを設定する中間証明書も一緒に設定する。クライアントがルートまでたどれない
ルート CA で、サーバの証明書を直接発行するルートは中間 CA の署名にだけ使い、オフラインにする
秘密鍵を CSR と一緒に CA に送るCA に渡すのは CSR だけ。秘密鍵は作った場所から動かさない
失効させたのに、CRL を公開していない新しい CRL を公開し、CRL 配布点から取れることを確かめるまでが失効
証明書の期限を人が覚えておく有効期間は短くなっていく。自動更新か、期限の通知を設定する
CRL 配布点の URL を、発行した後で変える発行済みの証明書は古い URL のまま。古い場所も、期限が切れるまで残す

うまくいかないとき

証明書のエラーは、チェーンのどの確認で止まったかが分かると原因を絞れます。openssl verify のエラーの番号と、止まった確認を並べると次のようになります。

エラー(openssl verify)どの確認で止まったか直し方error 20unable to get local issuer certificateつながり:発行者が見つからない中間証明書も送る・入れるerror 10certificate has expired期限:有効期間の外更新する・時計を見るerror 23certificate revoked失効:CRL に載っている新しい鍵で発行し直すerror 26unsuitable certificate purpose用途:EKU が合わない用途に合う証明書を使うerror 25path length constraint exceeded役割:pathlen を超えたCA の階層を見直すエラーの番号で、チェーンのどの確認で止まったかが分かる
図19 エラーの番号と、止まった確認

STEP 4・5 で見た error 20 と error 23 のほかに、残りの3つもテスト用の CA でわざと起こしてみました。まず、有効期間がすでに過ぎた証明書です。

期限切れの証明書を発行して検証する

openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout old.key -out old.csr -subj "/CN=old.example.test"
openssl ca -config ca.cnf -batch -extensions server_ext -startdate 20260101000000Z -enddate 20260301000000Z -in old.csr -out old.crt
openssl verify -CAfile root.crt -untrusted inter.crt old.crt
CN = old.example.test
error 10 at 0 depth lookup: certificate has expired
error old.crt: verification failed

次に、クライアント認証用(clientAuth)の証明書を、サーバ用(-purpose sslserver)として確かめた場合です。同じ証明書を、クライアント用として確かめると通ります。

用途が合わない(サーバ用として確かめる)

openssl verify -CAfile root.crt -untrusted inter.crt -purpose sslserver client.crt
CN = app01
error 26 at 0 depth lookup: unsuitable certificate purpose
error client.crt: verification failed

用途が合う(クライアント用として確かめる)

openssl verify -CAfile root.crt -untrusted inter.crt -purpose sslclient client.crt
client.crt: OK

最後に、pathlen:0 の中間 CA の下に、もう1つ CA(Demo Sub CA)を作って証明書を発行した場合です。OpenSSL は発行そのものは止めませんが、検証で失敗します。

pathlen を超えた CA で発行して検証する

printf "basicConstraints=critical,CA:TRUE\nkeyUsage=critical,keyCertSign,cRLSign\n" > sub.ext
openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout sub.key -out sub.csr -subj "/CN=Demo Sub CA"
openssl x509 -req -in sub.csr -CA inter.crt -CAkey inter.key -CAcreateserial -out sub.crt -days 30 -extfile sub.ext
openssl req -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout leaf2.key -out leaf2.csr -subj "/CN=leaf.example.test"
openssl x509 -req -in leaf2.csr -CA sub.crt -CAkey sub.key -CAcreateserial -out leaf2.crt -days 7
cat inter.crt sub.crt > untrusted2.pem
openssl verify -CAfile root.crt -untrusted untrusted2.pem leaf2.crt
CN = Demo Issuing CA
error 25 at 2 depth lookup: path length constraint exceeded
error leaf2.crt: verification failed

at 2 depth は、チェーンの下から3枚目(深さ 2、Demo Issuing CA)の pathlen:0 の制約で止まったことを表します。

エラー意味確かめること
unable to get local issuer certificate発行者の証明書が見つからない中間証明書を送っているか。社内 CA のルートを信頼済みストアに入れたか
certificate has expired有効期間を過ぎた証明書の notAfter。中間証明書の期限も。クライアントの時計
certificate revokedCRL や OCSP で失効と分かった新しい鍵で証明書を発行し直して入れ替える
unsuitable certificate purposeEKU が用途と合わないサーバ用は serverAuth、クライアント用は clientAuth が入った証明書を使う
path length constraint exceededpathlen の制約を超えたCA の階層が、上の CA の pathlen に収まっているか

企業での例

場面やること押さえどころ
社内の Web システムや API に、社内 CA の証明書を使うAD CS を2階層で作り、ルート証明書を社内の PC に配るルートはオフライン。AIA と CDP は発行前に決める
公開している API のサーバ証明書公的な CA の証明書を、ACME や Key Vault で自動更新する最長200日(2027年3月からは100日)。手作業の更新はやめる
社員の PC の秘密鍵が漏れたかもしれないその証明書を失効させ、CRL を公開する相手が新しい CRL を取るまでは使えてしまう
VPN や Wi-Fi で、機器を証明書で認証するクライアント認証用(clientAuth)の証明書を配る次の記事(mTLS)と同じ考え方

まとめ

項目内容
PKI とはCA が「この公開鍵は、この名前のもの」と署名して保証するしくみ
証明書の中身シリアル・発行者・有効期間・主体・公開鍵・拡張(CA:TRUE/FALSE・用途・SAN・CDP・AIA)と CA の署名
チェーンルート(自己署名・オフライン)→ 中間(発行 CA)→ サーバ。サーバは中間証明書も送る
確かめること1枚ずつ署名・期限・CA の立場・失効。サーバ証明書は名前と用途も
失効CRL(まとめて取る)と OCSP(1枚ずつ聞く)。公開して相手が取るまでが失効
今の流れ公的な TLS 証明書は最長200日から47日へ。更新の自動化が前提
Microsoft の場合Key Vault で期限と自動更新を、AD CS で社内の CA の階層と失効を管理する

参考にした資料

この記事は、次の標準と公式ドキュメントで内容を確かめて書きました。仕様や対応状況は変わることがあるので、最新の情報はリンク先で確かめてください。

あとがき

ルート CA から順に作ってみると、証明書の「つながり」は、発行者の名前と署名を1段ずつたどっているだけだと、手で確かめられました。一方で、失効は証明書そのものではなく CA が出すリストの側で起きることや、公開して相手が取るまで効かないことは、実際に CRL を作り直して初めて実感できたところです。次の記事では、この証明書をクライアントにも持たせて相手を確かめる mTLS を扱います。

コメント