0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenSSLでプライベートCAを作る(全15章)

0
Last updated at Posted at 2026-09-26

0. はじめに

この記事は、学んだ技術や知識についてを備忘録としてまとめることを目的にしている。今回はOpenSSLを用いたプライベートCA作成方法についてまとめる。

注意
この記事で作る証明書はすべて開発・検証専用です。本番環境では使わないでください。

記事が長くなったため、内容を5本に分けている。この記事は全体の目次であり、各章の本文は次の記事にある。

記事 収録する章 内容
mTLSとは何か ― TLSとの違いから証明書チェーンまで 2章 前提知識。手を動かさずに読む
OpenSSLでプライベートCAを作る ― 構築手順 3〜11章・13章 本編。ここで実際に証明書を作る
OpenSSLでプライベートCAを作る ― スクリプト全文 12章 手順をまとめたスクリプトの全文
【用語解説】OpenSSLでプライベートCAを作るときに出てくる用語 付録 用語の解説

章番号は5本を通して連番になっている。3章から11章まではcerts/配下を順に作っていく一続きの作業なので、記事を上から順に実行していけばよい。

なお、本文中に出てくる用語の解説は別記事にまとめてある。

本文中では次の形で参照する。

用語解説(別記事)

  • G01. ○○とは
  • G02. △△とは

1. 開発環境

  • macOS: 26.6
  • OpenSSL 3.6.3
  • 出口: nginx(ssl_client_certificateによるクライアント証明書検証)
  • 端末側: macOS

2. 基本概念

TLSとmTLSの違い、ハンドシェイクの流れ、証明書チェーンと信頼ストアのしくみを説明する。

→ この章を読む(mTLSとは何か)

3. 作成するCAの構成

これから作る証明書5枚と、その親子関係・有効期間を先に決めておく。

→ この章を読む(構築手順)

4. 事前準備

OpenSSL 3.xの用意、CAごとのディレクトリと台帳、CA設定ファイルを作る。

→ この章を読む(構築手順)

5. ルートCAを作成する

信頼の起点になるルートCAの鍵と自己署名証明書を作る。

→ この章を読む(構築手順)

6. 中間CAを作成する

中間CAの鍵とCSRを作り、ルートCAに署名してもらう。チェーンファイルもここで作る。

→ この章を読む(構築手順)

7. サーバ証明書を作成する

SANにホスト名を書いたサーバ証明書を、中間CAに署名してもらう。

→ この章を読む(構築手順)

8. クライアント証明書を作成する

端末に配るクライアント証明書を5枚発行し、.p12にまとめる。

→ この章を読む(構築手順)

9. 失効リスト(CRL)を作成する

証明書を1枚失効させ、失効リスト(CRL)を生成する。

→ この章を読む(構築手順)

10. 生成物を検証する

ここまでに作った証明書をopenssl verifyにかけ、チェーンと失効が効くことを確かめる。

→ この章を読む(構築手順)

11. nginxで動作確認する

nginxを立ててmTLSを有効にし、5枚のクライアント証明書が想定どおりの結果になるかを確認する。

→ この章を読む(構築手順)

12. スクリプト全文

ここまでの手順をまとめたシェルスクリプトの全文。

→ この章を読む(スクリプト全文)

13. 運用上の注意

秘密鍵の扱いと、検証が終わったあとの後始末。

→ この章を読む(構築手順)

14. まとめ

プライベートCAの作成手順を整理すると、次の5段階になる。

  1. 台帳を用意する — openssl caはファイルベースのCA運用ツール
  2. ルートCAを自己署名で作る — 信頼の起点
  3. 中間CAを作る — CSRを作り、ルートCAで署名する
  4. 末端の証明書を作る — サーバ(SAN必須)とクライアント(CNの値が識別子)
  5. チェーンファイルにまとめる — 用途によって中身が違う

作業中に詰まった箇所を一覧にしておく。

章 症状 原因
4.1 オプションが通らない macOS標準のopensslはLibreSSL
4.2 index.txtが無いと怒られる openssl caは台帳(index.txt / serial / crlnumber)が前提
7.3.3 拡張が入っていない証明書ができる -extfileを渡すと-extensionsの参照先がそのファイルになる
7.3.2 CNを書いたのにホスト名照合が通らない サーバ証明書はSANしか見られない(RFC 9525)
7.5.1 環境によって信頼されたりされなかったり ssl_certificateとssl_client_certificateに渡すPEMを取り違えている
8.2.1 同じCNの値で2枚目が発行できない unique_subject = noが要る
3.3 -daysに何を入れるか決まらない 上限は業界ルールであり、プライベートCAには適用されない
11.4 すべてのクライアント証明書が拒否される ssl_crlはチェーンの全段のCRLを要求する。ルートCAのCRLが無いと中間CAの段で止まる

証明書そのものより、openssl caが「ファイルベースのCA運用ツール」であるという前提を知っているかどうかで、かかる時間がだいぶ変わった。

15. 参考文献

記述の根拠にした資料である。(最終確認: 2026-09-15)

仕様(一次情報)

資料 URL この記事のどこで使ったか
RFC 8446 — The Transport Layer Security (TLS) Protocol Version 1.3 https://www.rfc-editor.org/rfc/rfc8446.html 2.2.3. mTLSのハンドシェイク(CertificateRequest / Certificate / CertificateVerify)、certificate_authorities拡張(§4.2.4, §4.3.2, §4.4)
RFC 9525 — Service Identity in TLS https://www.rfc-editor.org/rfc/rfc9525.html 7.3.2. サーバ証明書のCNを使ってはいけない根拠。2023年11月、RFC 6125を廃止
RFC 6125 — Representation and Verification of Domain-Based Application Service Identity https://www.rfc-editor.org/rfc/rfc6125.html 7.3.2. CN非推奨化の経緯(RFC 9525に廃止された)
RFC 2818 — HTTP Over TLS https://www.rfc-editor.org/rfc/rfc2818.html 7.3.2. 同上。SANが無ければCNを使う、とされていた時代の規定
RFC 7292 — PKCS #12: Personal Information Exchange Syntax v1.1 https://www.rfc-editor.org/rfc/rfc7292.html 8.4. .p12の仕様
RFC 5280 — Internet X.509 PKI Certificate and CRL Profile https://www.rfc-editor.org/rfc/rfc5280.html 2.3 / 3.1. 証明書とCRLの構造、basicConstraints / keyUsage / pathlen
RFC 2253 — Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names https://www.rfc-editor.org/rfc/rfc2253.html 2.3. nginxの$ssl_client_s_dnが従うDNの表記形式
RFC 5737 — IPv4 Address Blocks Reserved for Documentation https://www.rfc-editor.org/rfc/rfc5737.html 記事中の例で192.0.2.10を使っている理由

RFC 9525の該当箇所(引用)

The Common Name RDN MUST NOT be used to identify a service because it is not strongly typed (it is essentially free-form text) and therefore suffers from ambiguities in interpretation.

OpenSSL公式ドキュメント

資料 URL この記事のどこで使ったか
openssl ca https://docs.openssl.org/master/man1/openssl-ca/ 4.2 / 4.3 / 7.3 / 7.4 / 8.2 / 8.3 / 9. 台帳の必須性、unique_subjectの既定値、-extfileと-extensionsの関係、-startdate / -enddate、-revoke / -gencrl / -crlexts、ツールの位置づけ
openssl pkcs12 https://docs.openssl.org/master/man1/openssl-pkcs12/ 8.4. .p12の既定の暗号方式(AES-256-CBC + PBKDF2)とMAC(SHA256)
openssl verification options https://docs.openssl.org/master/man1/openssl-verification-options/ 11.1. -verify_depthの数え方

openssl caの記述(引用・要点)

  • database: "The text database file to use. Mandatory. This file must be present though initially it will be empty."
  • new_certs_dir: "Mandatory. It specifies the directory where new certificates will be placed."
  • -extfile: "An additional configuration file to read certificate extensions from (using its unnamed (default) section unless the -extensions option is also used)."
  • -extensions: "The section of the configuration file containing certificate extensions to be added when a certificate is issued (defaults to x509_extensions unless the -extfile option is used)."
  • ツールの位置づけ: "This command was originally meant as an example of how to do things in a CA. Its code does not have production quality."

openssl verification optionsの記述(引用)

Limit the certificate chain to num intermediate CA certificates. A maximal depth chain can have up to num+2 certificates, since neither the end-entity certificate nor the trust-anchor certificate count against the -verify_depth limit.

nginx公式ドキュメント

資料 URL この記事のどこで使ったか
Module ngx_http_ssl_module https://nginx.org/en/docs/http/ngx_http_ssl_module.html 2.5 / 7.5 / 9 / 11. 各ディレクティブの意味と$ssl_client_*変数
ngx_event_openssl.c(nginxのソース) https://github.com/nginx/nginx/blob/master/src/event/ngx_event_openssl.c 10.5. ssl_crlがX509_V_FLAG_CRL_CHECK_ALLを立てること

該当箇所(引用)

  • ssl_certificate: "If intermediate certificates should be specified in addition to a primary certificate, they should be specified in the same file in the following order: the primary certificate comes first, then the intermediate certificates."
  • ssl_client_certificate: "The list of certificates will be sent to clients. If this is not desired, the ssl_trusted_certificate directive can be used."
  • ssl_trusted_certificate: "In contrast to the certificate set by ssl_client_certificate, the list of these certificates will not be sent to clients."
  • ssl_verify_depth: 既定値は 1
  • ssl_crl: "When using intermediate certificates, their CRLs should be specified in the same file."

証明書の有効期間

資料 URL この記事のどこで使ったか
Apple — Requirements for trusted certificates in iOS 13 and macOS 10.15 https://support.apple.com/en-us/102028 3.3. 398日ルールと、その適用範囲(手動追加したルートCAは対象外)
CA/Browser Forum — Ballot SC-081v3 https://cabforum.org/2025/04/11/ballot-sc081v3-introduce-schedule-of-reducing-validity-and-data-reuse-periods/ 3.3. 有効期間の上限が業界団体の投票で決まること、398日→47日への段階的短縮

Appleの記述(引用)

TLS server certificates issued on or after September 1, 2020 00:00 GMT/UTC must not have a validity period greater than 398 days.

This change will not affect certificates issued from user-added or administrator-added Root CAs.

この2文目が、「プライベートCAには適用されない」の根拠である。

macOSのopensslがLibreSSLであること

資料 URL この記事のどこで使ったか
LibreSSL — Wikipedia https://en.wikipedia.org/wiki/LibreSSL 4.1. LibreSSLがOpenSSL 1.0.1gからのフォークであること、ABI互換が無いこと
drduh/macOS-Security-and-Privacy-Guide Issue #356 https://github.com/drduh/macOS-Security-and-Privacy-Guide/issues/356 4.1. macOSがLibreSSLを同梱しており、Homebrewのopensslがkeg-onlyである理由

手元での実行結果も併記しておく。

$ /usr/bin/openssl version
LibreSSL 3.3.6

本格的なCA運用ツール(参考)

資料 URL
step-ca https://smallstep.com/docs/step-ca/
cfssl https://github.com/cloudflare/cfssl

二次情報(補足的に参照)

有効期間の段階的短縮の中間ステップ(200日 / 100日)については、CA/Browser Forumの公式投票ページに具体的な日付の記載が無かったため、以下を参照した。一次情報ではない点に注意が必要である。

資料 URL
Sectigo — CA/B Forum Cuts SSL/TLS Certificate Lifespan to 47 Days https://www.sectigo.com/resource-library/sectigo-cab-reduce-ssl-tls-certificates-lifespan-47-days
AppViewX — CA/Browser Forum Certificate Validity Changes https://www.appviewx.com/blogs/ca-browser-forum-certificate-validity-changes/

一般向けの解説記事

資料 URL
トランスポート層セキュリティー(TLS)とは — IBM https://www.ibm.com/jp-ja/think/topics/transport-layer-security
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?