OpenSSL で構築した認証局 (CA) でサーバ証明書を発行する方法

ここでは「OpenSSL で認証局 (CA) を構築する手順」で紹介した手順に従って構築した認証局(CA)を使って、 SSL/TLS 通信で利用するサーバ証明書を発行する方法を説明します。

サーバ証明書があるときに Node + Express で SSL/TLS 通信を行う具体的な設定・コード例については、 「OpenSSL で構築した認証局 (CA) で発行したサーバ証明書を利用して HTTPS 通信する方法」をみてください。

1. サーバ証明書発行までの流れとポイント

1-1. サーバー証明書発行の流れ

HTTPS 通信を行うためには「サーバ証明書」が必要です。サーバ証明書を作成するにはまずは、ウェブサーバーの管理者が CSR (証明書署名要求 Certificate Signing Request) を作成するところから始めます。

CSR を作成するには、ウェブサーバーの秘密鍵が必要です。このため CSR の作成は、秘密鍵の作成、CSR の作成という2ステップになります。

また、CSR の作成の際には、具体的にどの国にある、何という会社・組織の、どんなホスト名のウェブサーバーであるかを入力する必要があります。

CSR はひとつのテキストファイルとして作成されます。

CSR を作成したら通常はそれを認証局 (CA) に送りデジタル署名してもらいます。この結果がサーバ証明書になります。

今回は CA も手元にあることを想定しています。つまり、自分でデジタル署名できる環境があることを想定しています。 CA の構築手順については「OpenSSL で認証局 (CA) を構築する手順」をみてください。

1-2. SAN (サブジェクトの別名) の設定が必要

CSR の作成時にひとつ注意点があります。

以前はウェブサーバーのホスト名は、CSR 作成時のコモンネーム (CN) の値として設定するので十分でした。 しかし、現在は複数のウェブサイトがひとつの証明書で利用できるのに伴い、 X.509 証明書の拡張領域である subjectAltName (SAN と略されます) というところに設定する必要があります。

Chrome ブラウザはバージョン 58 以降では commonName ではなく、subjectAltName のみをチェックするようになりました。 このため subjectAltName が設定されていない場合に "NET::ERR_CERT_COMMON_NAME_INVALID" などのエラーが表示されます。

SAN 情報を設定するために、 CSR 作成時にも追加の設定ファイルが必要になりますし、CA 側の設定でも X.509 の拡張領域の取り扱いのオプションを設定する必要があります。

中間CAでデジタル署名する際の copy_extensions = copy オプションによって、 CSR の拡張領域の情報がコピーされます。

2. サーバ証明書を作成してみよう

前提として認証局(CA)は「OpenSSL で認証局 (CA) を構築する手順」に沿って作成しているものとします。 もし異なる場合はパスや設定ファイル (openssl.cfg) などが異なるために、ここで紹介する手順通りには動作しない場合がありますのでご注意ください。

2-1. OpenSSL を用いた CSR の作成方法

さて、まずはウェブサーバー管理者として CSR (Certificate Signing Request) を作成しましょう。

次の内容を foo.example.com.cfg として作成して、C:\CA に配置してください。

[ req ]
default_bits       = 2048
distinguished_name = req_distinguished_name
req_extensions     = req_ext

[ req_distinguished_name ]
countryName                 = Country Name (2 letter code)
countryName_default         = US
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = California
localityName                = Locality Name (eg, city)
localityName_default        = Torrance
organizationName            = Organization Name (eg, company)
organizationName_default    = Foo Company
commonName                  = Common Name (e.g. server FQDN or YOUR name)
commonName_default          = foo.example.com

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1   = foo.example.com
DNS.2   = bar.test.com
DNS.3   = localhost

ここで alt_names セクションの DNS 名 (DNS name) は、 あなたの環境に合わせて適当に書き換えてください。

*_default のエントリーは、コマンドラインでのデフォルト値 (何も入力せずに Enter を押下したときに使われる値) になります。あらかじめ、よく使う値に書き換えておくと便利です。

この設定ファイルでは、foo.example.com や bar.test.com というウェブサーバーにアクセスする想定としています。

DNS 名といっても DNS サーバーのアドレスなどを設定するのではなく、「DNS で解決される名前」のことです。 RFC3280 の 4.2.1.7 "Subject Alternative Name" などで DNS name という書き方をしているのでその通りにかきました。

ウェブサーバーで使う証明書の場合通常は、ウェブサーバーのホスト名になります。

次のコマンドでウェブサーバーの秘密鍵と CSR を作成します。

>cd /d C:\CA
>openssl genrsa -aes256 -out intermediate\private\foo.example.com.key.pem 2048
>openssl req -config foo.example.com.cfg -key intermediate\private\foo.example.com.key.pem -new -sha256 -out intermediate\csr\foo.example.com.csr.pem

C:\intermediate\csr\foo.example.com.csr.pem が CSR です。

次のコマンドで CSR の内容を確認できます。

>cd /d C:\CA
>openssl req -noout -text -in intermediate\csr\foo.example.com.csr.pem

出力内容の中で特に、 SAN (Subject Alternative Name) が正しく設定されているか確認してください。

...
 X509v3 Subject Alternative Name:
    DNS:foo.example.com, DNS:bar.test.com, DNS:localhost

2-2. OpenSSL を用いたサーバ証明書の発行

さて、上で作成した CSR を基に、次は認証局(CA)の作業として、サーバ証明書を作成します。

>cd /d C:\CA
>openssl ca -config intermediate\openssl.cfg -extensions server_cert -days 5000 -notext -md sha256 -in intermediate\csr\foo.example.com.csr.pem -out intermediate\certs\foo.example.com.cert.pem

この結果作成されたファイル C:\intermediate\certs\foo.example.com.cert.pem がサーバ証明書になります。

キーファイル C:\intermediate\private\foo.example.com.key.pem と 証明書ファイル C:\intermediate\certs\foo.example.com.cert.pem を使うことで、 HTTPS通信を行うことができます。

以上で、サーバ証明書が発行できました。

これらのファイルと Node (Express) を用いて HTTPS 通信を行う具体例については「OpenSSL で構築した認証局 (CA) で発行したサーバ証明書を利用して HTTPS 通信する方法」で紹介します。

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

© 2024 Node.js 入門