メインコンテンツまでスキップ

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 の両方を含めることが多い

IDサービスでの証明書

OAuth/OIDC での使用

IDサービスにおける証明書の用途:

┌─────────────────────────────────────────────────────────────┐
│ │
│ 1. TLSサーバー証明書 │
│ ・認可サーバーのHTTPS │
│ ・必須(OAuth 2.0仕様) │
│ │
│ 2. JWKs(JSON Web Key Set) │
│ ・IDトークンの署名検証用公開鍵 │
│ ・jwks_uri で公開 │
│ │
│ 3. クライアント認証用証明書 │
│ ・private_key_jwt 認証 │
│ ・mTLS認証 │
│ │
│ 4. 証明書バインドトークン │
│ ・FAPI要件 │
│ ・トークンとクライアント証明書の紐付け │
│ │
└─────────────────────────────────────────────────────────────┘

private_key_jwt 認証

private_key_jwt でのクライアント認証:

┌─────────────────────────────────────────────────────────────┐
│ クライアント 認可サーバー │
│ │ │ │
│ │ 1. クライアントアサーション作成 │ │
│ │ JWT = { │ │
│ │ iss: client_id, │ │
│ │ sub: client_id, │ │
│ │ aud: token_endpoint, │ │
│ │ exp: 有効期限 │ │
│ │ } │ │
│ │ 署名: クライアントの秘密鍵 │ │
│ │ │ │
│ │ 2. トークンリクエスト │ │
│ │ ─────────────────────────────────→ │ │
│ │ client_assertion_type= │ │
│ │ urn:ietf:params:oauth: │ │
│ │ client-assertion-type:jwt-bearer│ │
│ │ client_assertion=JWT │ │
│ │ │ │
│ │ 3. 署名検証 │ │
│ │ JWKsから公開鍵取得 │
│ │ │ │
└─────────────────────────────────────────────────────────────┘

証明書管理のベストプラクティス

┌─────────────────────────────────────────────────────────────┐
│ 証明書管理のベストプラクティス │
├─────────────────────────────────────────────────────────────┤
│ │
│ 【秘密鍵の保護】 │
│ ✓ 適切な権限設定(600、root所有) │
│ ✓ HSM(Hardware Security Module)の使用を検討 │
│ ✓ 秘密鍵のバックアップと安全な保管 │
│ ✓ パスフレーズによる暗号化(運用とのトレードオフ) │
│ │
│ 【有効期限の管理】 │
│ ✓ 証明書の有効期限を監視 │
│ ✓ 更新作業の自動化(Let's Encrypt + certbot等) │
│ ✓ 期限切れ前のアラート設定 │
│ │
│ 【証明書チェーン】 │
│ ✓ 中間証明書を正しく設定 │
│ ✓ ルート証明書は含めない │
│ ✓ SSL Labsなどで検証 │
│ │
│ 【失効対応】 │
│ ✓ OCSP Staplingを有効化 │
│ ✓ 秘密鍵漏洩時の失効手順を準備 │
│ ✓ 新しい証明書の迅速な発行体制 │
│ │
│ 【監査とコンプライアンス】 │
│ ✓ Certificate Transparency (CT) ログの監視 │
│ ✓ 発行された証明書の棚卸し │
│ ✓ 暗号アルゴリズムの定期的な見直し │
│ │
└─────────────────────────────────────────────────────────────┘

まとめ

PKIと証明書の重要ポイント:

1. PKIは公開鍵の信頼性を保証する仕組み
- 認証局(CA)による証明
- 証明書チェーンによる信頼の連鎖

2. X.509証明書の構造を理解する
- Subject、Issuer、有効期間
- 拡張フィールド(SAN、Key Usage等)

3. 証明書チェーンを正しく設定する
- サーバー証明書 + 中間証明書
- ルート証明書は含めない

4. 証明書の失効確認を有効化する
- OCSP Stapling推奨
- CRLは補助的に

5. 証明書管理を自動化する
- Let's Encrypt + 自動更新
- 有効期限の監視

次のステップ