OpenSSL で認証局 (CA) を構築する手順 (Windows)

ここでは OpenSSL を利用して公開鍵証明書認証局 (CA, Certificate Authority) を構築する手順について説明します。

認証局を構築、といってももちろん、家を建てるとか物を作るというのではありません。 デジタル証明書の署名要求に応えられるように、CA 証明書やコマンドなどの環境を整えておくということです。

ここでは Windows 上にルート CA と中間 CA を作成する手順を載せておきます。

1. OpenSSL のインストール

OpenSSLのツールセットをバイナリで配布しているサイトがありますので、そちらでダウンロードしてインストールしてください。

OpenSSL Wiki - Binaries

私は 64bit Windows 版のパッケージを C:\OpenSSL-Win64 にインストールして、システム環境変数 PATHC:\OpenSSL-Win64\bin を追加しました。

コマンドプロンプトを開き、バージョンを確認すると次のようになりました。

> openssl version
OpenSSL 1.1.1d  10 Sep 2019

2. CA 用のディレクトリの作成

ここでは C:\CA というフォルダ以下に環境を構築するものとします。 もし同じ名前のフォルダが既にあって使われていたら、適当にパスを読み替えてください。

C:\CA 内に、次の内容を setup.bat という名前で作成してください。

@mkdir root\certs
@mkdir root\crl
@mkdir root\newcerts
@mkdir root\private
@mkdir root\csr
@type nul > root\index.txt
@type nul > root\crlnumber
@echo 1000 > root\serial
@mkdir intermediate\certs
@mkdir intermediate\crl
@mkdir intermediate\newcerts
@mkdir intermediate\private
@mkdir intermediate\csr
@type nul > intermediate\index.txt
@type nul > intermediate\crlnumber
@echo 1000 > intermediate\serial

コマンドプロンプトを開き C:\CA に移動して、setup.bat を実行してください。

> cd /d C:\CA
> setup

3. ルート CA の作成

3-1. OpenSSL 設定ファイルの準備

C:\CA\root 内に以下の内容を openssl.cfg という名前で作成してください。

[ ca ]
default_ca    = CA_default

[ CA_default ]
dir              = C:\\CA\\root
certs            = C:\\CA\\root\\certs
crl_dir          = C:\\CA\\root\\crl
database         = C:\\CA\\root\\index.txt
new_certs_dir    = C:\\CA\\root\\newcerts
serial           = C:\\CA\\root\\serial
crlnumber        = C:\\CA\\root\\crlnumber
crl              = C:\\CA\\root\\crl.pem
certificate      = C:\\CA\\root\\certs\\ca.cert.pem
private_key      = C:\\CA\\root\\private\\ca.key.pem
name_opt         = ca_default
cert_opt         = ca_default
crl_extensions   = crl_ext
default_days     = 365
default_crl_days = 30
default_md       = sha256
preserve         = no
policy           = policy_match

[ policy_match ]
countryName             = match
stateOrProvinceName     = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
default_bits            = 2048
distinguished_name      = req_distinguished_name
x509_extensions         = v3_ca
string_mask             = utf8only
default_md              = sha256

[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = US
countryName_min                 = 2
countryName_max                 = 2
stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = California
localityName                    = Locality Name (eg, city)
localityName_default            = Los Angeles
0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = Ace Internet Inc.
organizationalUnitName          = Organizational Unit Name (eg, section)
organizationalUnitName_default  = http://ace.example.com/
commonName                      = Common Name (e.g. server FQDN or YOUR name)
commonName_default              = Ace Internet Root CA
commonName_max                  = 64
emailAddress                    = Email Address
emailAddress_default            = ace@example.com
emailAddress_max                = 64

[ server_cert ]
basicConstraints       = CA:FALSE
nsCertType             = server
nsComment              = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage               = critical, digitalSignature, keyEncipherment
extendedKeyUsage       = serverAuth

[ v3_ca ]
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints       = critical,CA:true
keyUsage               = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints       = critical,CA:true, pathlen:0
keyUsage               = critical, digitalSignature, cRLSign, keyCertSign

[ crl_ext ]
authorityKeyIdentifier = keyid:always

3-2. 秘密鍵とルートCA証明書の作成

コマンドプロンプトから、次のコマンドを実行します。

特に秘密鍵を生成するときなどはパスフレーズの入力を求められる時がありますが、この資料では全て password と入力することにします。 実際に利用する場合はあなたのセキュリティの要件に合わせて、適宜強固なパスフレーズを使ってください。ただし、秘密鍵にアクセスするたびに必要となるので、忘れないように注意してください。

> cd /d C:\CA
> openssl genrsa -aes256 -out root\private\ca.key.pem 4096
> openssl req -config root\openssl.cfg -key root\private\ca.key.pem -new -x509 -days 9999 -sha256 -extensions v3_ca -out root\certs\ca.cert.pem

ここで作成した ca.key.pemca.key.pem がそれぞれ、 ルートCAの秘密鍵とルートCA証明書です。

認証局の名前などは上で作成した設定ファイルでデフォルト値を利用する場合は、 質問に単に Enter を押してください。

ルートCA証明書の内容は次のコマンドで表示できます。

> cd /d C:\CA
> openssl x509 -noout -text -in root\certs\ca.cert.pem

3-3. Windows にルートCA証明書を登録

ルートCA証明書は Windows の証明書ストアに格納することで、ブラウザから認識できるようになります。

上記の手順では PEM 形式の証明書が作成されますが、Windows に登録するためには PKCS #7 (p7b) 形式に変換する必要があります。

次のコマンドで PKCS #7 形式の証明書を作成します。

> cd /d C:\CA
> openssl crl2pkcs7 -nocrl -certfile root\certs\ca.cert.pem -out root\certs\ca.cert.p7b

Windows に今作成した CA証明書を登録しましょう。

Windows の「コンピュータ証明書の管理」(Manage Computer Certificates) を開きます。コントロールパネルに「ユーザー証明書の管理」と「コンピュータ証明書の管理」の二種類あるので間違えないようにしてください。

「信頼されたルート証明機関」(Trusted Root Certification Authorities) の下の「証明書」を右クリックし、表示されたコンテキストメニューから「全てのタスク」から「インポート」を選択します。

上のコマンドを実行すると、C:\CA\root\certs\ca.cert.p7b に証明書が作成されていますので、それを選択します。

証明書ストアを指定するところでは、「参照」ボタンをクリックして表示されたポップアップで「物理ストアを表示する」(Show physical stores) をチェックします。 そして、「信頼されたルート証明機関」の下の「レジストリ」を選びます。

画面の指示に従い登録を済ませ、表示を更新すると「信頼されたルート証明機関」の下の「証明書」の中に、上で作成したルートCA証明書が表示されるはずです。

これでルートCAの準備ができました。

次に中間CAを作成します。

4. 中間CAの作成

通常、認証局には大きく分けて二種類あり、ひとつはルートCAともうひとつは中間CAです。ルートCAは中間CAの認証を行う(証明書の発行を行う)ために使われ、HTTPS 通信で使うサーバ証明書などの署名は中間CAで行います。

4-1. OpenSSL 設定ファイルの準備

C:\CA\intermediate 内に以下の内容を openssl.cfg という名前で作成してください。

[ ca ]
default_ca    = CA_default

[ CA_default ]
dir              = C:\\CA\\intermediate
certs            = C:\\CA\\intermediate\\certs
crl_dir          = C:\\CA\\intermediate\\crl
database         = C:\\CA\\intermediate\\index.txt
new_certs_dir    = C:\\CA\\intermediate\\newcerts
serial           = C:\\CA\\intermediate\\serial
crlnumber        = C:\\CA\\intermediate\\crlnumber
crl              = C:\\CA\\intermediate\\crl.pem
certificate      = C:\\CA\\intermediate\\certs\\intermediate.cert.pem
private_key      = C:\\CA\\intermediate\\private\\intermediate.key.pem
x509_extensions  = usr_cert
name_opt         = ca_default
cert_opt         = ca_default
crl_extensions   = crl_ext
default_days     = 365
default_crl_days = 30
default_md       = sha256
preserve         = no
policy           = policy_anything
copy_extensions  = copy

[ policy_anything ]
countryName            = optional
stateOrProvinceName    = optional
localityName           = optional
organizationName       = optional
organizationalUnitName = optional
commonName             = supplied
emailAddress           = optional

[ req ]
default_bits           = 2048
distinguished_name     = req_distinguished_name
x509_extensions        = v3_ca
string_mask            = utf8only
default_md             = sha256

[ req_distinguished_name ]
countryName                    = Country Name (2 letter code)
countryName_default            = US
countryName_min                = 2
countryName_max                = 2
stateOrProvinceName            = State or Province Name (full name)
stateOrProvinceName_default    = California
localityName                   = Locality Name (eg, city)
localityName_default           = Los Angeles
0.organizationName             = Organization Name (eg, company)
0.organizationName_default     = Ace Internet Inc.
organizationalUnitName         = Organizational Unit Name (eg, section)
organizationalUnitName_default = http://ace.example.com/
commonName                     = Common Name (e.g. server FQDN or YOUR name)
commonName_default             = Ace Internet Code Signing CA
commonName_max                 = 64
emailAddress                   = Email Address
emailAddress_default           = ace@example.com
emailAddress_max               = 64

[ server_cert ]
basicConstraints       = CA:FALSE
nsCertType             = server
nsComment              = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage               = critical, digitalSignature, keyEncipherment
extendedKeyUsage       = serverAuth

[ v3_ca ]
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints       = critical,CA:true
keyUsage               = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints       = critical,CA:true, pathlen:0
keyUsage               = critical, digitalSignature, cRLSign, keyCertSign

[ crl_ext ]
authorityKeyIdentifier = keyid:always

4-2. 中間CA証明書の発行

次のコマンドで中間CAの秘密鍵を生成し、CA証明書のCSRを作成して、ルートCAにて中間CAの証明書を発行します。

> cd /d C:\CA
> openssl genrsa -aes256 -out intermediate\private\intermediate.key.pem 4096
> openssl req -config intermediate\openssl.cfg -new -sha256 -key intermediate\private\intermediate.key.pem -out intermediate\csr\intermediate.csr.pem
> openssl ca -config root\openssl.cfg -extensions v3_intermediate_ca -days 5000 -notext -md sha256 -in intermediate\csr\intermediate.csr.pem -out intermediate\certs\intermediate.cert.pem

4-3. Windows に中間CA証明書を登録

ルートCA証明書と同様に、中間CA証明書も Windows に登録します。PEM のままでは登録できないので、 PKCS #7 (p7b) に変換します。

> cd /d C:\CA
> openssl crl2pkcs7 -nocrl -certfile intermediate\certs\intermediate.cert.pem -out intermediate\certs\intermediate.cert.p7b

生成された intermediate.cert.p7b を Windows のコンピュータ証明書管理画面で登録します。

「中間証明機関」の下の「証明書」フォルダにインポートしてください。その他の手順は、上で見たルートCA証明書の登録と同様です。

以上でルートCAと中間CAを構築することができました。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Node.js 入門