手を動かして学ぶ!CAと証明書【ブログリレー 3日目】

プログラミング

この記事はデジクリブログリレー企画 3日目の記事です。

こんにちは。最近人々にノベルゲームの沼に突き落とされたcordx56です。

ところで、CAや証明書周りの実践的な記事って少ないなと感じませんか? 今回の記事では、CAについて簡単に説明をして、実際に手を動かしてプライベートCAの構築、サーバ証明書の発行、発行した証明書を利用したWebサーバの構築、そしてブラウザからのアクセスまでを解説していきたいと思います。

CA(Certification Authority)とは

CAとは一体何なのでしょうか。

CAとは日本語で言うと認証局であり、電子証明書を発行する機関です。 その他にも役割は存在しますが、ここでは説明を割愛します。

CAにはパブリックCAとプライベートCAの二種類があります。

パブリックCAは厳しい運用規程に則り運用されており、広くOSやブラウザなどにデフォルトで信頼される認証局として登録されています。

一方で、プライベートCAとは、一般にオレオレ認証局などと呼ばれており、一般的には信頼されない認証局です。 ですが、会社など各機関で自由に運用規程を決定できます。 プライベートに認証局を構築し、必要なコンピュータに対してそれらを信頼された認証局として登録することにより、その認証局の発行した証明書を信頼して通信を行えるようになります。 ローカルで運用しているサーバなど、パブリックなCAから証明書を発行してもらうのが難しい場合かつ利用者が限られている場合などに有効です(最近では、Let's EncryptやACMなどの登場により、公開されているサーバでは簡単にパブリックなCAから証明書を発行してもらえるようになりました。)。

プライベートCAの構築

では、ここからはプライベートCAを実際に構築してみましょう。

ここから先はUbuntu 20.04、OpenSSL 1.1.1f 31 Mar 2020を使っている想定で書いていきます。

秘密鍵の生成

まずは秘密鍵を生成します。 鍵の長さは安全のために4096bitにしておきましょう。

$ openssl genrsa -out ca.key 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
............................................................................................................................................................................................................................++++
.............................................................................................................................................................................++++
e is 65537 (0x010001)

これでca.keyという秘密鍵ファイルが生成されます。

CSR(Certificate Signing Request)の生成

次に、CSRというものを生成します。 CSRとは、証明書への署名をCAに依頼するためのもので、証明書を必要としている組織の公開鍵とその組織自体の情報を含み、含まれている公開鍵で署名されています。

組織に関する情報は対話的に入力します。

$ openssl req -new -key ca.key -sha512 -out ca.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:Example
Email Address []:example@example.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

すべて入力し終わると、ca.csrが生成されていると思います。

CA証明書の発行

最後に、自己署名認証局の証明書を発行します。

$ openssl x509 -sha512 -days 3650 -in ca.csr -req -signkey ca.key -out cacert.pem
Signature ok
subject=C = JP, ST = Tokyo, O = Example, CN = Example, emailAddress = example@example.com
Getting Private key

これでcacert.pemが生成されていると思います。

プライベートCAで証明書を発行する

では、実際にWebサーバに配置する証明書を作っていきましょう。

ここでは、localhostというFQDNに対して証明書を発行します。

秘密鍵の生成

まず秘密鍵を生成します。

$ openssl genrsa -out localhost-private.key 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
......++++
...........................................................................................................++++
e is 65537 (0x010001)

CSRの作成

次にCSRを作成していきます。

$ openssl req -new -key localhost-private.key -sha512 -out localhost-server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:example@example.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

証明書の発行

最後に、証明書の発行をしていきます。

その前に、ちょっとした下準備が必要です。 以下は環境によって異なるかもしれません。 /usr/lib/ssl/openssl.cnf の設定に従って変更してください。

$ mkdir -p ./demoCA/newcerts
$ touch demoCA/index.txt
$ echo "00" > demoCA/serial

もしわからない場合、次のコマンドを実行して、そのエラーメッセージを読んで解決するのでも問題ないと思います。

$ openssl ca -days 3650 -in localhost-server.csr -out localhost-server.pem -keyfile ca.key -cert cacert.pem
Using configuration from /usr/lib/ssl/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 0 (0x0)
        Validity
            Not Before: Aug 25 12:36:58 2021 GMT
            Not After : Aug 23 12:36:58 2031 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = Example
            commonName                = localhost
            emailAddress              = example@example.com
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                43:EF:76:C2:38:34:F0:10:46:8B:CE:33:B7:46:08:3A:0B:10:04:76
            X509v3 Authority Key Identifier:
                DirName:/C=JP/ST=Tokyo/O=Example/CN=Example/emailAddress=example@example.com
                serial:5A:93:AF:56:37:59:FE:F9:B8:7A:D3:69:ED:A5:BA:3C:91:68:3C:41

Certificate is to be certified until Aug 23 12:36:58 2031 GMT (3650 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

これで証明書の発行は完了です。

実際に発行した証明書を利用する

では、実際に発行した証明書を利用してみましょう。

nginxの設定フォルダに localhost-server.pemlocalhost-private.key を配置し、次のような設定を書き加え、nginxを起動します。

server {
    listen       443 ssl;
    listen  [::]:443 ssl;
    server_name  localhost;

    ssl_certificate localhost-server.pem;
    ssl_certificate_key localhost-private.key;
    (以下に設定が続く)
}

これでnginxを起動し、 https://localhost にアクセスしてみると、次のような画面が表示されると思います。

Firefoxエラー画面

これはFirefoxでの例ですが、恐らく他のブラウザでも似たようなエラーが出ることでしょう。

これはブラウザにプライベートCAの証明書がインストールされていないので発生するエラーです。 では、ブラウザにプライベートCAの証明書をインストールしましょう。

この手順はブラウザごとに異なるので、詳細は割愛しますが、Firefoxだと、設定 > プライバシーとセキュリティー > 証明書を表示 > 認証局証明書 > インポートから実行できます。

いずれのブラウザでも、 cacert.pem をインポートしてください。

終わったら、再度 https://localhost にアクセスしてみましょう。 今度は正常にWebページが表示されるはずです。

認証局の表示

さいごに

今回の記事では、CAについて軽く説明したのち、実際に手を動かしてプライベートCAの構築、SSL/TLSサーバ証明書の発行、発行した証明書を利用したWebサーバの構築まで行いました。

プライベートCAの構築なんかは、今であればACMプライベートCAでやってしまうのが妥当かもしれません(まぁ毎月$400を払える場合ですが……)。 ですが、個人運用でやる場合や勉強のためにやる場合などは、こういった知識が役に立つことでしょう。 是非習得していってください!

今回の記事を書くにあたり、プロフェッショナルSSL/TLSを参考にさせていただきました。 興味のある方は是非手に取ってみてください。

参考文献