Chromeで使えるオレオレ証明書を作成する方法


opensslを使用してChromeで使える自己署名証明書(オレオレ証明書)を作成する方法を解説します。
また、簡単に生成できるツールも用意しました。よければご活用下さい(dockerが必要です)

発端

ローカル環境でhttpsを実現するために、オレオレ(自己署名)SSL証明書を作成したのですがchromeではNET::ERR_CERT_COMMON_NAME_INVALIDとなってしまいました。

原因は、Chromeの仕様変更により、ドメイン名のチェックをCommon Name(通称CN)ではなくSubject Alternative Names(通称SAN)を参考にする様になったためだそうです。

ここではSubject Alternative Namesを含んだ自己署名サーバ証明書の作り方を解説します。

(追記) 自己署名証明書を作成するツールを作りました。

self-sign-cert
dockerがインストールされている必要がありますが、1コマンドで自己署名証明書が作成できます。
詳しい使い方は該当リポジトリのReadmeを参照してください。

手順

SANを含んだサーバ証明書を生成する

適当なディレクトリに移動する

mkdir /work
cd /work

SANの設定が書かれたテキストファイルを用意します。
ドメイン名とIPアドレスは自身の環境に合わせて変更してください。
ファイル名は何でもよいですが、ここではsubjectnames.txtとしました。

subjectnames.txt
subjectAltName = DNS:your-domain.com, IP:127.0.0.1

秘密鍵(server.key)、署名要求(server.csr)、サーバ証明書(server.crt)を生成します。
サーバ証明書を作成する際に-extfileオプションでSANを埋め込むのがキモです。

# 秘密鍵(server.key)を生成する
openssl genrsa 2048 > server.key
# 秘密鍵から署名要求(server.csr)を生成する
# your-domain.comは自身の環境に合わせて変更してください。
openssl req -new -key server.key -subj "/C=JP/ST=Some-State/O=Some-Org/CN=your-domain.com" > server.csr
# 署名要求を秘密鍵で署名してサーバ証明書を作成する
openssl x509 -days 3650 -req -extfile subjectnames.txt -signkey server.key < server.csr > server.crt

生成したサーバ証明書の内容を確認する

openssl x509 -in server.crt -text -noout

以下の様にCommon NameとSubject Alternative Namesが出力されていればOK

Nginxの設定

NginxでSSLを使うための設定を追加します。
ここでは/etc/nginx/conf.d/default.confを修正しています。

server {
    listen 80;
    listen 443 ssl;
    ssl_certificate     /work/server.crt; # サーバ証明書のパスを指定
    ssl_certificate_key /work/server.key; # 秘密鍵のパスを指定

    server_name your-domain.com; # CN, SANと合わせる

    ...

nginxの設定のテスト&再読み込み
※環境によりコマンドが異なる場合があります。

nginx -t
nginx reload

Chromeに信頼できるサーバ証明書として登録する

サーバ証明書(server.crt)をChromeに登録します。
手順は以下のページを参考にしてください。

Google Chromeへ証明書ファイルをインポートするには | サポート・お申し込みガイド | GMOグローバルサイン【公式】

動作確認

chromeからhttps://your-domain.comにアクセスしてNET::ERR_CERT_COMMON_NAME_INVALIDが発生しなければOKです。

あとがき

自己署名証明書を作るのにわりと手間取りまして、よくよく考えるとopenssl全然分からんし署名要求って何?サーバ証明書って結局なんなの??登場人物多すぎ!!(泣)というレベルで全然わかってませんでした。
そんな訳で、整理も兼ねて図を書きましたところ、それなりに分かりやすい図が出来た(気がする)のでシェアさせてください。
これを見れば「自己署名証明書の作成って結局何やってんの?」というのが分かる様になってopensslの一連のコマンドが何をやっているのかもイメージできる様になるはずです。

では早速ですが、まず、一般的な「認証局に署名して貰ってサーバ証明書を作成する」ケースです。

①自身のサーバ上で秘密鍵を生成する
②自身のサーバ上で秘密鍵から署名要求を生成する
署名要求を認証局に渡して署名してもらう。これがサーバ証明書となる。
④クライアントにはあらかじめ認証局のサーバ証明書を「信頼できる証明書」として登録しておく。

続いて、今回の「自己署名でサーバ証明書を作成」するケースです。

①、②は同じです。
こちらのケースでは自己署名なので認証局は登場しません。
ではどうするかというと③で自身の秘密鍵を使って署名します。
そうして出来たサーバ証明書を「信頼するサーバ証明書」としてクライアントに登録します。

今回使用したopensslコマンドとの対応ですが

openssl genrsa秘密鍵を生成するコマンドで図中①に対応
openssl reqが秘密鍵から署名要求を生成するコマンドで図中②に対応
openssl x509が署名要求を署名してサーバ証明書を作成するコマンドで図中③に対応

となっております。

以上、
どうでしょうか、なんとなくサーバ証明書を生成する一連の流れがイメージできたでしょうか?
理解の一助となっていれば幸いです。