PKIと証明書
このドキュメントの目的
PKI(Public Key Infrastructure) とX.509証明書の仕組みを理解し、証明書の発行・管理・検証について学びます。
PKIとは
PKI(Public Key Infrastructure / 公開鍵基盤):
- 公開鍵暗号を安全に運用するための仕組み
- 「この公開鍵は本当にこの人/組織のものか」を保証
- 証明書、認証局(CA)、失効管理などで構成
PKIが解決する問題:
【問題】公開鍵の信頼性
┌─────────────────────────────────────────────────────────────┐
│ Aさんの公開鍵だと言われたが... │
│ │
│ 「これはAさんの公開鍵です」 │
│ ↓ │
│ 本当にAさんの公開鍵? │
│ 攻撃者がAさんになりすましていない? │
└───────────────────────────────────────────── ────────────────┘
【解決】信頼できる第三者(CA)による証明
┌─────────────────────────────────────────────────────────────┐
│ 認証局(CA)が「この公開鍵はAさんのものです」と証明 │
│ │
│ 認証局の署名付き証明書 │
│ ↓ │
│ CAを信頼 → Aさんの公開鍵を信頼 │
└─────────────────────────────────────────────────────────────┘
PKIの構成要素
┌─────────────────────────────────────────────────────────────┐
│ PKIの主要構成要素 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ │
│ │ ルート認証局 │ ← 信頼の起点(トラストアンカー) │
│ │ (Root CA) │ 自己署名証明書を持つ │
│ └────────┬────────┘ │
│ │ 証明書発行 │
│ ┌────────┴────────┐ │
│ │ 中間認証局 │ ← ルートCAの代わりに証明書を発行 │
│ │ (Intermediate │ ルートCAの秘密鍵を保護 │
│ │ CA) │ │
│ └────────┬────────┘ │
│ │ 証明書発行 │
│ ┌────────┴────────┐ │
│ │ エンドエン ティティ│ ← サーバー、ユーザー、デバイス等 │
│ │ (End Entity) │ 実際に使用される証明書 │
│ └─────────────────┘ │
│ │
│ その他の要素: │
│ ・登録局(RA): 証明書申請の受付・審査 │
│ ・リポジトリ: 証明書と失効リストの公開 │
│ ・CRL/OCSP: 証明書の失効確認 │
│ │
└─────────────────────────────────────────────────────────────┘
X.509証明書
証明書の構造
X.509証明書の構造:
┌─────────────────────────────────────────────────────────────┐
│ X.509 証明書 │
├────────────────────────────────────────────────── ───────────┤
│ │
│ 【TBSCertificate(署名対象)】 │
│ ├── Version: v3 │
│ ├── Serial Number: 一意の識別子 │
│ ├── Signature Algorithm: SHA256withRSA など │
│ ├── Issuer: 発行者(CA)の識別名 │
│ │ └── CN=Example CA, O=Example Inc, C=JP │
│ ├── Validity: 有効期間 │
│ │ ├── Not Before: 開始日時 │
│ │ └── Not After: 終了日時 │
│ ├── Subject: 主体者の識別名 │
│ │ └── CN=www.example.com, O=Example Inc, C=JP │
│ ├── Subject Public Key Info: 公開鍵 │
│ │ ├── Algorithm: RSA, EC など │
│ │ └── Public Key: 公開鍵データ │
│ └── Extensions: 拡張フィールド(v3) │
│ ├── Subject Alternative Name (SAN) │
│ ├── Key Usage │
│ ├── Extended Key Usage │
│ ├── Basic Constraints │
│ └── ... │
│ │
│ 【Signature Algorithm】SHA256withRSA など │
│ 【Signature】CAの秘密鍵による署名 │
│ │
└─────────────────────────────────────────────────────────────┘
主要な拡張フィールド
X.509 v3 拡張フィールド:
┌─────────────────────────────────────────────────────────────┐
│ 拡張フィールド │ 説明 │
├─────────────────────────────────────────────────────────────┤
│ Subject Alternative Name │ 追加のホスト名やIPアドレス │
│ (SAN) │ 例: DNS:www.example.com, │
│ │ DNS:example.com │
├─────────────────────────────────────────────────────────────┤
│ Key Usage │ 鍵の使用目的 │
│ │ digitalSignature, keyEncipherment│
│ │ keyCertSign(CA用) │
├────────────────────────────── ───────────────────────────────┤
│ Extended Key Usage │ 拡張鍵用途 │
│ │ serverAuth: TLSサーバー認証 │
│ │ clientAuth: TLSクライアント認証 │
│ │ codeSigning: コード署名 │
├─────────────────────────────────────────────────────────────┤
│ Basic Constraints │ CA証明書かどうか │
│ │ CA:TRUE, pathLen:0 │
├─────────────────────────────────────────────────────────────┤
│ CRL Distribution Points │ CRLの取得先URL │
├─────────────────────────────────────────── ──────────────────┤
│ Authority Information │ OCSP応答者URL、発行者証明書URL │
│ Access (AIA) │ │
└─────────────────────────────────────────────────────────────┘
証明書チェーン
信頼の連鎖
証明書チェーン(Certificate Chain):
┌─────────────────────────────────────────────────────────────┐
│ │
│ ┌─────────────────┐ │
│ │ ルートCA証明書 │ ← ブラウザ/OSに事前インストール │
│ │ (自己署名) │ トラストストアに格納 │
│ │ │ │
│ │ Subject: Root CA │
│ │ Issuer: Root CA ← 自分で自分を署名 │
│ └────────┬────────┘ │
│ │ ルートCAの秘密鍵で署名 │
│ ↓ │
│ ┌─────────────────┐ │
│ │ 中間CA証明書 │ ← サーバーから送信 │
│ │ │ │
│ │ Subject: Intermediate CA │
│ │ Issuer: Root CA │
│ └────────┬────────┘ │
│ │ 中間CAの秘密鍵で署名 │
│ ↓ │
│ ┌─────────────────┐ │
│ │ サーバー証明書 │ ← サーバーか ら送信 │
│ │ │ │
│ │ Subject: www.example.com │
│ │ Issuer: Intermediate CA │
│ └─────────────────┘ │
│ │
│ 検証の流れ(下から上へ): │
│ 1. サーバー証明書の署名を中間CA公開鍵で検証 │
│ 2. 中間CA証明書の署名をルートCA公開鍵で検証 │
│ 3. ルートCAがトラストストアにあれば信頼 │
│ │
└─────────────────────────────────────────────────────────────┘
チェーンの設定
サーバー設定での証明書チェーン:
正しい設定:
サーバー証明書 + 中間CA証明書 を連結したファイルを使用
-----BEGIN CERTIFICATE-----
(サーバー証明書)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(中間CA証明書)
-----END CERTIFICATE-----
Nginx設定例:
ssl_certificate /etc/ssl/certs/fullchain.pem; # チェーン全体
ssl_certificate_key /etc/ssl/private/server.key;
よくある間違い:
✗ サーバー証明書のみ(中間証明書なし)
→ 一部のクライアントで検証失敗
✗ ルート証明書も含める
→ 不要(クライアントが持っている)
証明書の発行
CSR(Certificate Signing Request)
証明書発行の流れ:
┌─────────────────────────────────────────────────────────────┐
│ │
│ 1. 鍵ペア生成(申請者側) │
│ ┌─────────────────┐ │
│ │ 秘密鍵 │ ← 絶対に外部に出さない │
│ │ 公開鍵 │ │
│ └─────────────────┘ │
│ │
│ 2. CSR作成(申請者側) │
│ ┌─────────────────┐ │
│ │ CSR │ │
│ │ ・公開鍵 │ │
│ │ ・Subject情報 │ CN, O, OU, C など │
│ │ ・申請者の署名 │ │
│ └─────────────────┘ │
│ │ │
│ ↓ CSRをCAに送信 │
│ │
│ 3. 審査・発行(CA側) │
│ ┌─────────────────┐ │
│ │ ・申請内容の審査 │ ドメイン所有権、組織の実在等 │
│ │ ・証明書の発行 │ CAの秘密鍵で署名 │
│ └─────────────────┘ │
│ │ │
│ ↓ 証明書を返送 │
│ │
│ 4. 証明書のインストール(申請者側) │
│ サーバーに証明書と秘密鍵を設定 │
│ │
└─────────────────────────────────────────────────────────────┘
OpenSSLでの操作
# 1. 秘密鍵の生成(RSA 2048ビット)
openssl genrsa -out server.key 2048
# 2. CSRの生成
openssl req -new -key server.key -out server.csr \
-subj "/C=JP/ST=Tokyo/L=Shibuya/O=Example Inc/CN=www.example.com"
# 3. CSRの内容確認
openssl req -in server.csr -text -noout
# 4. 証明書の確認
openssl x509 -in server.crt -text -noout
# 5. 証明書と秘密鍵の対応確認
openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in server.key | openssl md5
# → 同じ値なら対応している
Let's Encrypt(自動発行)
Let's Encrypt による自動発行:
┌─────────────────────────────────────────────────────────────┐
│ ACME プロトコル │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. ドメイン所有権の証明 │
│ ┌─────────────────┐ │
│ │ HTTP-01チャレンジ │ │
│ │ /.well-known/ │ ← 指定ファイルを配置 │
│ │ acme-challenge/ │ │
│ └─────────────────┘ │
│ または │
│ ┌─────────────────┐ │
│ │ DNS-01チャレンジ │ │
│ │ _acme-challenge │ ← TXTレコードを設定 │
│ └─────────────────┘ │
│ │
│ 2. 証明書の自動発行・更新 │
│ certbot renew │
│ → 有効期限30日前に自動更新 │
│ │
│ 特徴: │
│ ・無料 │
│ ・DV証明書のみ │
│ ・有効期間90日(短い = セキュリティ向上) │
│ ・自動更新が前提 の設計 │
│ │
└─────────────────────────────────────────────────────────────┘
証明書の失効
失効が必要なケース
証明書を失効させる必要がある場合:
┌─────────────────────────────────────────────────────────────┐
│ ・秘密鍵が漏洩した(または漏洩の疑い) │
│ ・証明書の情報が変更された(組織名変更等) │
│ ・CAが不正発行した │
│ ・証明書が不要になった │
└─────────────────────────────────────────────────────────────┘
有効期限が切れる前でも、失効させることで即座に無効化できる
CRL(Certificate Revocation List)
CRL(証明書失効リスト):
┌─────────────────────────────────────────────────────────────┐
│ CRL │
├─────────────────────────────────────────────────────────────┤
│ 発行者: Intermediate CA │
│ 発行日: 2024-01-15 │
│ 次回更新: 2024-01-22 │
│ │
│ 失効証明書リスト: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Serial: 12345, 失効日: 2024-01-10, 理由: keyCompromise│ │
│ │ Serial: 12346, 失効日: 2024-01-12, 理由: cessationOfOperation│
│ │ ... │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ CAの署名 │
└─────────────────────────────────────────────────────────────┘
課題:
・CRLファイルが大きくなる
・更新間隔までは古い情報を使用
・リアルタイム性に欠ける
OCSP(Online Certificate Status Protocol)
OCSP(オンライン証明書状態プロトコル):
┌─────────────────────────────────────────────────────────────┐
│ クライアント OCSP応答者 │
│ │ │ │
│ │ ── OCSPリクエスト ─────────→ │ │
│ │ 「Serial: 12345 の │ │
│ │ 状態を教えて」 │ │
│ │ │ │
│ │ ←── OCSP応答 ───────────── │ │
│ │ 「good / revoked / │ │
│ │ unknown」 │ │
│ │ │ │
└─────────────────────────────────────────────────────────────┘
利点:
・リアルタイムで状態確認可能
・CRLより軽量
課題:
・OCSP応答者への依存
・プライバシー(アクセス先がわかる)
OCSP Stapling
OCSP Stapling:
┌─────────────────────────────────────────────────────────────┐
│ │
│ 通常のOCSP: │
│ クライアント → OCSP応答者 → 応答 │
│ 問題: 追加の通信、遅延、プライバシー │
│ │
│ OCSP Stapling: │
│ サーバー → OCSP応答者 → 応答を取得 │
│ サーバー → クライアント → 証明書 + OCSP応答を一緒に送信 │
│ │
│ 利点: │
│ ・クライアントの追加通信不要 │
│ ・高速 │
│ ・プライバシー保護 │
│ │
└─────────────────────────────────────────────────────────────┘
Nginx設定:
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/certs/ca-bundle.crt;
証明書の種類と用途
用途別の証明書
┌─────────────────────────────────────────────────────────────┐
│ 用途 │ Extended Key Usage │ 説明 │
├─────────────────────────────────────────────────────────────┤
│ TLSサーバー認証 │ serverAuth │ Webサーバー等 │
│ │ 1.3.6.1.5.5.7.3.1 │ │
├─────────────────────────────────────────────────────────────┤
│ TLSクライアント │ clientAuth │ mTLS認証 │
│ 認証 │ 1.3.6.1.5.5.7.3.2 │ │
├─────────────────────────────────────────────────────────────┤
│ コード署名 │ codeSigning │ ソフトウェア │
│ │ 1.3.6.1.5.5.7.3.3 │ 署名 │
├─────────────────────────────────────────────────────────────┤
│ メール保護 │ emailProtection │ S/MIME │
│ │ 1.3.6.1.5.5.7.3.4 │ │
├─────────────────────────────────────────────────────────────┤
│ タイムスタンプ │ timeStamping │ 時刻証明 │
│ │ 1.3.6.1.5.5.7.3.8 │ │
└─────────────────────────────────────────────────────────────┘
ワイルドカード証明書
ワイルドカード証明書:
CN = *.example.com
カバーする範囲:
✓ www.example.com
✓ api.example.com
✓ mail.example.com
カバーしない範囲:
✗ example.com(ベースドメイン)
✗ sub.www.example.com(2階層以上)
注意点:
・1つの秘密鍵を複数サーバーで共有
・漏洩時の影響が大きい
・SANに *.example.com と example.com の両方を含めることが多い