ボクボク証明書(その1)

ボクボク証明書とは、自己署名証明書ではあるがオレオレ証明書よりはすこしマシな証明書のことである。

まず、証明書について基本的なことを確認しておく。

ここでいう証明書とは、インターネットのサーバにブラウザでアクセスするときにサーバが正統(正当?)であることを証明するための証明書のことである。

昔のインターネットでは、サーバ証明書などというものは必要なかったが、次第に利用されることが増え、最近では証明書を提示しないサーバとの通信は「安全でない通信」「保護されていない通信」などと表示されるようになった。

証明書を提示する通信は、「HTTPS」と呼ばれるプロトコルを使用する。

「HTTPS」とは、SecureなHTTPという意味である。

例えばオンラインショッピングでクレジットカード情報や住所等を入力するサイトである場合、そのサーバとの通信を他者に知られないように暗号化する必要がある。

HTTPSの通信が暗号化された通信であるという認識はほとんどの人が持っているだろうが、当たり前のことであるが、暗号化するには通信相手が本当に自分の通信したい相手なのかを確認する必要がある。

暗号化しているから安心だ、と、有名サイトを装った偽のサイト、いわゆるフィッシングサイトに接続してしまわないようにする必要である。

そのためにHTTPS通信ではサーバが証明書を提示し、クライアントはその証明書によりサーバがホンモノであることを確認して初めて「保護された通信」がおこなわれるのである。

しかし皆さんはおそらく『証明書がどうこうというのは知っているけど別にそれをいちいち確認してないけど』と思っているだろう。私もそうである。

サーバーがホンモノかどうか、つまり証明書が信頼できるかどうかは、ブラウザが判断している。

何をもって正統だと判断するか。

それは、証明書の発行者を見るのである。

そして、その発行者が信頼できる発行者であれば、その証明書は信頼できるとみなすのである。

ではどうやって発行者が信頼できるとみなすのか。

それは、「信頼できる証明書発行者リスト」というものを参照するのである。

それはあなたのパソコンの中にもある。


が、疑い深い人は、まだ安心できず「その『信頼できる証明書発行者リスト』が信頼できるとどうやって判断するのか、と思うだろう。


そしてここでようやくあなたの出番である。

あなたが使うパソコンにある、「信頼できる証明書発行者リスト」が信頼できるものであると、あなたが判断すれば、それを参照しているブラウザの判断も正しいとみなす。

あなたはそんなリストを登録した覚えはない、見たことすらない、というかもしれないが、

おそらくHTTPS通信というものはそういう建前で動いている。

自分で登録していなければ、ブラウザインストール時あるいはOSインストール時(インストール済みPCであれば購入時)に登録されるリストを信頼すると、あなたが受け入れていることになっているのだ。


前置きが長くなったが、ボクボク証明書を説明するために必要な前提条件である。

さて、「オレオレ証明書」とは、「発行者が自分自身である証明書」のことである。

今回発行する証明書も自分自身で署名しているのだが、一応「信頼」してもらえる証明書になる。

そのカラクリは、先ほど説明した「信頼できる証明書発行者リスト」にある。

もうお気づきであろう。

ボクボク証明書というのは、「信頼できる証明書発行者リスト」に、あなたという証明書発行者を追加してもらうことにより、信頼できる証明書としてもらうのである。


御託はこれくらいにして、以下、実践。

以前やった時とはいろいろ変わっていたので改めて手順を書く。


apacheとopensslのバージョンは以下


# httpd -v

Server version: Apache/2.4.37 (centos)

Server built:   Jun  8 2020 20:14:33


# openssl version

OpenSSL 1.1.1c FIPS  28 May 2019


手順の流れ

1.CA証明書作成

 1-1. CAの秘密鍵作成

 1-2. CA証明書のCSR発行

 1-3. CA証明書のCSRにCAの秘密鍵を用いて署名


2.WEBサーバの証明書作成

 2-1. WEBサーバの秘密鍵を作成

 2-2. WEBサーバ証明書のCSRを発行

 2-3. WEBサーバ証明書にCAの秘密鍵を用いて署名

 2-4. Apacheの設定ファイルで発行した証明書と秘密鍵の場所を指定


3. 動作確認

 3-1. CA証明書をクライアントにインストール

 3-2. サイトにアクセス


手順

以下手順では必要に応じてカレントディレクトリを移動しているので、ファイル名を指定する箇所のパス名は実施する状況に応じて変更が必要な場合があります。

ドメイン名、ホスト名等は必要に応じて変更しているので参考程度にしてください。


1.CA証明書作成

1.1 CAの秘密鍵作成

# openssl genrsa -aes256 -out ./cakey.pem 2048

Generating RSA private key, 2048 bit long modulus (2 primes)

...................................................................................+++++

..........................................+++++

e is 65537 (0x010001)

Enter pass phrase for ./cakey.pem:(パスフレーズを入力)

Verifying - Enter pass phrase for ./cakey.pem:(パスフレーズを入力)


1.2 CA証明書のCSR発行

openssl req -new -key ./cakey.pem -out ./cacert.csr


※-keyでCAの秘密鍵ファイルを、-outで発行するCSRファイルを指定する。


# openssl req -new -key ./cakey.pem -out ./cacert.csr

Enter pass phrase for ./cakey.pem:(CAの秘密鍵のパスフレーズを入力)

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) [XX]:JP

State or Province Name (full name) []:Tokyo

Locality Name (eg, city) [Default City]:Shinjuku

Organization Name (eg, company) [Default Company Ltd]:

Organizational Unit Name (eg, section) []:

Common Name (eg, your name or your server's hostname) []:ca.monqy.net

Email Address []:


Please enter the following 'extra' attributes

to be sent with your certificate request

A challenge password []:

An optional company name []:

最後のチャレンジパスワードは書いてあるようにextraの設定なので入れなくてもよい。


1.2 CA証明書のCSRにCAの秘密鍵を用いて署名

# openssl x509 -days 825 -in ./cacert.csr -req -signkey ./cakey.pem -out ./cacert.pem

Signature ok

subject=C = JP, ST = Tokyo, L = Shinjuku, O = Default Company Ltd, CN = ca.monkey.net

Getting Private key

Enter pass phrase for ./cakey.pem:(CAの秘密鍵のパスフレーズ)


2.WEBサーバー証明書作成

以下が前提である。

opensslの設定ファイルの場所: /etc/pki/tls/openssl.cnf

openssl.cnfの設定

default_ca = CA_default
dir = /etc/pki/CA     

CAの秘密鍵の保存ディレクトリ: /etc/pki/CA/private/cakey.pem

WEBサーバ証明書等の保存ディレクトリ: /etc/pki/SSL


2.1 WEBサーバーの秘密鍵作成

# openssl genrsa -aes256 -out ./serverkey.pem 2048

Generating RSA private key, 2048 bit long modulus (2 primes)
............................................................................+++++
................+++++
e is 65537 (0x010001)
Enter pass phrase for ./server.key:(パスフレーズを入力)
Verifying - Enter pass phrase for ./server.key:(確認のためパスフレーズを再入力)


これはCAの秘密鍵を作ったときと全く同じことをしている。


2.2 WEBサーバーのCSR作成

[root@jesus SSL]# openssl req -new -key ./server.key -out ./server.csr

Enter pass phrase for ./server.key:(WEBサーバーの秘密鍵のパスフレーズ)

140637670844224:error:28078065:UI routines:UI_set_result_ex:result too small:crypto/ui/ui_lib.c:903:You must type in 4 to 1023 characters

Enter pass phrase for ./server.key:(WEBサーバーの秘密鍵のパスフレーズ)

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) [XX]:JP

State or Province Name (full name) []:Tokyo

Locality Name (eg, city) [Default City]:Xxxxx

Organization Name (eg, company) [Default Company Ltd]:

Organizational Unit Name (eg, section) []:

Common Name (eg, your name or your server's hostname) []:*.monqy.net

Email Address []:


Please enter the following 'extra' attributes

to be sent with your certificate request

A challenge password []:

An optional company name []:


これもCAと同じことをしている。指定する秘密鍵がWEBサーバのものであることと、Common Nameが違うだけである。

Common Nameは *.monqy.net としているが、
こうしておくとホスト名が変わっても同じ証明書が使えるそうである。

たとえば、www.monqy.net でも www2.monqy.net でも、というように。


Common NameはCNと略され、サーバにアクセスするときのfqdnである必要がある。
fqdnとCNが異なっていると正しい証明書とみなされない。
さらに、今はCNがfqdnと一致しているだけでなく、もう一か所別の設定でもfqdnを記述する必要がある。
(後述)



---------------------------------------------
(追記)
openssl.confの設定により場所が異なるが、下記ファイルが必要

index.txt
serial.txt

今やったのだと /etc/pki/CA

index.txt はあれば中身がなくてもよいが
serial.txt は4桁の数字が書いてある必要があるらしい
今やったのは 0001 で成功した。
1  だけだと失敗する
-----------------------------------------

2.3 WEBサーバ証明書にCAの秘密鍵を用いて署名

以下のように書いたテキストを作る(san.txtとする)

subjectAltName=DNS:www.monqy.net

そして、署名の際に最後に以下のようなオプションを付けて署名する。
-extfile san.txt


openssl ca -config /etc/pki/tls/openssl.cnf -in /etc/pki/SSL/server.csr -keyfile /etc
/pki/CA/private/cakey.pem -cert /etc/pki/CA/cacert.pem -out server.crt -extfile san.txt
Using configuration from /etc/pki/tls/openssl.cnf
Enter pass phrase for /etc/pki/CA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 0 (0x0)
        Validity
            Not Before: Oct 11 01:25:48 2020 GMT
            Not After : Oct  9 01:25:48 2030 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = Default Company Ltd
            commonName                = *.monkey.net
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                31:D5:35:FC:B3:F9:6F:F0:29:84:47:4A:7C:B5:CB:8F:67:D0:26:2A
            X509v3 Authority Key Identifier:
                DirName:/C=JP/ST=Tokyo/O=Default Company Ltd/CN=*.monkey.net
                serial:5C:C5:FC:36:68:EF:F0:0A:CF:AF:DE:75:E5:1E:E6:4B:83:68:2C:38

Certificate is to be certified until Oct  9 01:25:48 2030 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

確認が2回来るのでyを入力する。
有効期間が10年間になっているが、デフォルトは1年である。

openssl.cnfの下記の設定で変更できる。
default_days   = 3650


-extfileで指定した「subjectAltName」であるが、最近はCNだけではなくこちらも見るようである。

これをやらないとchromeでは NET::ERR_CERT_COMMON_NAME_INVALID のエラーになる。

(参考)
https://www.pistolfly.com/weblog/2017/06/chrome%E3%81%A7-neterr_cert_common_name_invalid-%E3%82%A8%E3%83%A9%E3%83%BC.html

ここの記述によると、最近のchromeはcnは観ずにSANのみを見るらしい。


2-4. Apacheの設定ファイルで発行した証明書と秘密鍵の場所を指定

/etc/httpd/conf.d/ssl.conf


ServerName www.monqy.net:443

SSLProtocol all -SSLv3

SSLCertificateFile /etc/pki/SSL/server.crt

SSLCertificateKeyFile /etc/pki/SSL/server.key


ServerNameのfqdnがあっていることも確認

httpd再起動




3.動作確認

3.1 CA証明書のインストール

CA証明書をクライアント(Windows10)にダウンロードし、拡張子 .crt にして保存する。

/etc/pki/CA/cacert.pem
ca.crt

ca.crtをダブルクリックすると証明書の内容が表示される。
「証明書のインストール」をクリックし、「ローカルコンピューター」「信頼されたルート証明機関」にインストールする。

※ここでなくてもよいかもしれないが、ここにインストールして確認した。

3.2 ブラウザでアクセス

Chrome, Edge, FireFoxでかくに...!!!

FireFoxでは信頼されない!!

「誰かがこのサイトに偽装しようとしている可能性があります。続行しないでください。
 
ウェブサイトは証明書で同一性を証明します。証明書の発行者が不明、証明書が自己署名、またはサーバーが正しい中間証明書を送信していないため、Firefox は www.monqy.net を信頼しません。
 
エラーコード: SEC_ERROR_UNKNOWN_ISSUER」



chromeとedgeで問題なかったので、念のためFireFoxでも見ておくかと思ったらこのザマだ。


エラーメッセージについて調べると、単にCA証明書が見つからないというだけのようだ。
FireFoxは例の「信頼されたルート証明機関」を見ていないのか?

「オプション」「プライバシーとセキュリティ」「証明書」「証明書を表示...」
「認証局証明書」に認証局証明書の一覧がある。

今回作成してインストールした証明書はない。
FireFoxは独自の場所に信頼するCA証明書のリストを持っているようだ。

ここに今回作成したCA証明書をインポートしてから接続すると、
ブラウザにエラーは表示されなくなった。

しかし、証明書を表示すると「Mozillaが承認していない発行者の証明書で検証された接続です」と表示される。

これも消したいな...