【IT備忘録】 プライベート認証局による証明書の作成 | 仕事の覚書き

仕事の覚書き

メモメモ

0. 前書き

一言で言ってしまえば 「オレオレ証明書」 であることに変わりはない。しかし、いろいろ眺めているうちに、オレオレ証明書にも、自ら認証局を建て、証明書を発行している 「オレオレ証明書」 もあれば、完全な自己署名で使っている 「オレオレ証明書」 もあることに気が付いた。比率からすれば、圧倒的に多いのは後者である。
「動けばそれで良いのよ~っ♪」 的な調子で書かれた記事は、まず後者である(笑)

では、どちらが良いのか?

そもそも、使われている技術は、「腐っても鯛」 の公開鍵暗号技術である。例え鍵長が短くて脆弱であるとは言っても、それなりのコストは掛かる。
「お宝」 が中にあることが解かっていれば、それなりに頑張って 「ハックしてやろう!」 と思うかも知れないが、そうでなければ、狙ってくるのは市中のパソコンに侵入し、ゾンビ化を狙っているスパマー連中くらい(苦笑)

名の知れた大企業や政府地方公共団体などであれば、侵入されてウェブの書き換えなどが行われたらニュースになったりするものの、通常は、会社でウェブを建てても、一般はまず見向きもせず。「銀行口座番号だとか、決済に関わる情報が関わらない限りは SSL なんて不要…」 と思いたくなるような状況ではあるが、最近うるさい個人情報問題などもあり、ログイン ID やパスワードといったアカウント情報も含め、こういったものには SSL を掛けるのが基本。
日本でも携帯電話が出たての頃(docomo でモトローラの MicroTAC なんかが使われていた時代)は、電波にスクランブルが掛かっていなかったので、アマチュア無線などの無線機さえあれば、市中の電話が聞き放題(苦笑)
スマホやタブレットにノートパソコンなど WiFi 経由で使われるのが一般的になってる以上、裸のデータの垂れ流しは、スクランブルの掛かっていない携帯電話のようなもの。また、ウェブなどで、アクセスログにユーザ ID やパスワードが残るなんていうのは 「適切と言える運用状況にある」 とは決して言えない。

そういう意味では、SSL はオレオレでも何でも良いから、掛けた方がマシ。オレオレ認証の場合は、安全面での問題…と言うよりは、証明書から公的な認証局をたどれないので、「認証がなされていない」 とか 「確認できない」 的なメッセージが表示されてしまうことにより、利用者が一瞬 「ドキッ」 としてしまうことの弊害の方が大きい…という意見も正しいことは正しい。が、しかし、それも、昨今の金融系偽装サイトの乱立を見ると、一概にそうも言えない時代に入りつつあるようではある。

【補足】【重要】 OpenSSL Hearbleed 脆弱性の確認

認証関連を始める前に、最近大きな話題になった OpenSSL のハートブリード脆弱性に対する対応状況について確認 しておきましょう。
yum リポジトリを使用している場合は "yum list installed | grep openssl " で、現在インストールされている OpenSSL のバージョンとパッケージの確認ができます。また、openssl コマンドを実行してバージョンやパッケージを確認する場合は "openssl version -a" で確認します。
CentOS6 の場合は openssl-1.0.1e-16.el6_5.7 以上であれば、ハートブリード脆弱性問題の対策が取られているので問題ありません。但し、一般に脆弱性の影響を受ける openssl は version 1.0.1 ~ 1.0.1f1.0.2-beta 並びに 1.0.2-beta1 とされており、このため、自らソースをコンパイルして取り込んでいる等、CentOS6 ディストリビューション以外のものを用いている場合は openssl 1.0.1g へのアップグレードが必要なものもあります。このような場合は、他の OS の場合を含め、それぞれ対応状況が異なるため、別途、個別に確認願います。

1. プライベート認証局を建てる

1.1 事前準備

(1) CA スクリプト (/etc/pki/tls/misc/CA) を編集し、有効期限を変更する
$CADAYS を変更することで 「認証局用 CA」 の有効期限最大長の変更が可能。デフォルトは3年固定。もう一方の $DAYS は 「サーバ・その他用 CA」 の証明書の有効期限。こちらは、値が定義されていない (文字列長が 0 であると) 有効期限は1年に設定される。

(2) ユーザのデフォルト情報の準備 (入力簡略化のため)
openssl の構成定義ファイル openssl.cnf (/etc/pki/tls/openssl.cnf) を編集する。これは、特定の利用者の情報を入力する定義ファイルではなく、あくまでも、利用者情報の入力を促す際に使用される入力テンプレートなのだが、入力の問い合わせに対して何回も入力するのが煩わしいので、省力化のために自分の情報をデフォルト値としてここに書き込んでおく。
countryName_default = JP  ← 大文字アルファベット2文字による国名表記
stateOrProvinceName_default =  ← 県名
localityName_default =  ← 都市名など
0.organizationName_default =  ← 会社・団体名
1.organizationName_default =  ← 下部組織名
organizationalUnitName_default =  ← 部署名
emailAddress_default =  ← 連絡先 email アドレス
CA のフィールドは、認証書の照合に使われるフィールド (match) と、任意(オプション)のフィールド (optional)、並びに、照合には用いられないが、入力が必須のフィールド (supplied) のいずれかに分類される。この分類は個々の CA の 「ポリシ (policy)」 として規定されており、デフォルトでは、「policy_match」 ポリシと 「policy_anything」 ポリシが用意されている。
最初の 「policy_match」 は、countryName ・stateOrProvinceName ・organizationName が照合用 (match) として使用され、commonName は必須 (supplied)。その他は任意 (optional) となっている。システムのデフォルトは、この 「policy_match」 が設定されている。
必要な場合は、これらも適宜修正する必要があるが、まあ、オレオレの場合はだいたいこのままで使用するケースが大半である。

(3) (対象となる証明書毎の)構成定義ファイルの仕分け
上記で作成した構成定義ファイルを、作成しようとする証明書の種別(認証局・サーバ・クライアント)毎に複製し、必要な微修正を施しておく。これは、作業のノウハウのようなもので、技術的には必須ではないが、あとあと作業が混乱してくるので、事前にこのような整理をした方が良い…というお話。ここでは、上記 (2) で作成した openssl.cnf の複製 openssl-ca.cnf ・ openssl-server.cnf ・ openssl-client.cnf を作成しておく。
ファイル名は、本人が、認証対象と認証種別の違いを区別出来れば、何でも構わない。
ここで、これらの複製ファイル間で異なる重要なフィールドは、basicConstraints nsCertType そしてデフォルト値としては記入されていない commonName である。最初の2つのフィールドは事前に修正しておく方が間違いが少ない。変更は以下のとおり:
認証局用証明書 (openssl-ca.cnf)   サーバ用証明書 (openssl-server.cf)   クライアント用証明書 (openssl-client.cnf)  
basicConstraints = CA:TRUE basicConstraints = CA:FALSE basicConstraints = CA:FALSE
nsCertType = mailCA, sslCA nsCertType = server nsCertType = client, email, objsign
<CA名など(まあ適当)> <サイトのサーバ名 【重要】> <認証したいクライアント名(まあ適当)>

1.2 認証局用証明書の作成

(1) 認証局の証明書を作成する
以下のコマンドを実行する:
     cd /etc/pki/tls
     SSLEAY_CONFIG="/etc/pki/tls/openssl-ca.cnf"
     /etc/pki/tls/misc/CA -newca
○ ここで入力するパスフレーズは、認証局用のパスフレーズ のもの。
○ 入力値にデフォルト値が表示される場合は、そのままリターンを押すとデフォルト値が設定される。
○ CommonName には認証局名称などを設定する。(例: Human Resource Management CA など)
○ このコマンドを実行すると /etc/pki/CA ディレクトリ下に、以下のファイルが生成される: cacert.pem (認証局の証明書: 認証局の秘密鍵 cakey.pem で署名した認証局の公開鍵)、careq.pem (認証局の署名リクエスト CSR)、index.txt (証明書管理情報)、index.txt.attr (属性)、index.txt.old (ひとつ前のバックアップ)。また /etc/pki/CA 下の serial が更新されるほか、/etc/pki/CA/private 下に cakey.pem (認証局の秘密鍵) が作成される。

1.3 サーバ用証明書の作成
 
(1) サーバの秘密鍵と公開鍵を作成する
以下のコマンドを実行する:
     cd /etc/pki/tls
     DAYS="-days 1825"
     SSLEAY_CONFIG="/etc/pki/tls/openssl-server.cnf"
     /etc/pki/tls/misc/CA -newreq
○ ここで入力するパスフレーズは、サーバ認証用のパスフレーズ のもの。
○ サーバ認証の CommonName は、対象とするサーバの名称を正確に記述する。
○ このコマンドを実行するとカレントディレクトリ下に newkey.pem (サーバの秘密鍵) と newreq.pem (署名のないサーバの公開鍵 CSR) が作成される。 

(2) サーバの公開鍵に認証局の署名をする
     cd /etc/pki/tls
     SSLEAY_CONFIG="/etc/pki/tls/openssl-server.cnf"
     /etc/pki/tls/misc/CA -sign
○ ここで入力するパスフレーズは、認証局用のパスフレーズ のもの。
○ このコマンドを実行するとカレントディレクトリ下に newcert.pem (認証局の署名が成されたサーバ証明書) が作成される。

(3) 作成したサーバ証明書および秘密鍵をインストールする
     mv /etc/pki/tls/newcert.pem  /etc/pki/dovecot/certs/www.example.com.crt
     mv /etc/pki/tls/newkey.pem /etc/pki/dovecot/private/www.example.com.key.withoutpass

(4) 必要に応じて PEM形式の証明書を作成する
     openssl x509 -in /etc/pki/dovecot/certs/www.example.com.crt -outform PEM -out /etc/pki/dovecot/certs/www.example.com.pem

(5) サーバ用秘密鍵にパスフレーズを埋め込む(システム起動時のパスフレーズ入力を抑止する)
     openssl rsa -in /etc/pki/dovecot/private/www.example.com.key.withoutpass -out /etc/pki/dovecot/private/www.example.com.key
○ ここで入力するパスフレーズは、サーバ認証用のパスフレーズ のもの。

1.4 クライアント証明書の作成

実際の運営サイトで、クライアント証明書を使用するのは、現在のところ、かなり稀な状況であると言える。ケースとしては、個人の場合は、何かしらの特権を持った管理者が特定の作業をする際に、特定の端末などからしかアクセス出来ないように制約を課すようなケース。あるいは、協業している企業など組織間でシステムを接続し、組織毎にアクセス制御を行いたいような場合に、システム間の割符として使用するようなケースである。
末端の利用者のログインなどの手間を省くためだけに、クライアント認証を用いるのは、証明書の発行から配布・インストールのほか、事故の際の証明書の失効など多くの手間が掛かることから、高度なセキュリティ管理が求められるオペレーションなどは、まだ妥当と考えられるが、そうでない場合は、オンラインバンキングなど、かなり情報資産的リスクが高いものに限定されるのではないだろうか。

まあ、適用事例などは、ゆくゆく調べることにして、クライアント証明書の作り方は以下のとおり:

(1) クライアントの秘密鍵と公開鍵を作成する
以下のコマンドを実行する:
     cd /etc/pki/tls
     DAYS="-days 1825"
     SSLEAY_CONFIG="/etc/pki/tls/openssl-client.cnf"
     /etc/pki/tls/misc/CA -newreq
○ ここで入力するパスフレーズは、クライアント認証用のパスフレーズ のもの。
○ クライアント認証の CommonName は、対象とするクライアントの識別子等を入力する。email アドレスなども、クライアントに関連した情報を入力する。クライアントの端末識別番号などを入れるような運用もあるかも知れないし、認証書に規定された email アカウントのアクセスのみに限定するような運用をするかも知れないが、いずれにせよ、これらは、運用者あるいは認証者のポリシ・スキーム次第である。 
○ このコマンドを実行するとカレントディレクトリ下に newkey.pem (クライアントの秘密鍵) と newreq.pem (署名のないクライアントの公開鍵 CSR) が作成される。 

(2) クライアントの公開鍵に認証局の署名をする
     cd /etc/pki/tls
     SSLEAY_CONFIG="/etc/pki/tls/openssl-client.cnf"
     /etc/pki/tls/misc/CA -sign
○ ここで入力するパスフレーズは、認証局用のパスフレーズ のもの。
○ このコマンドを実行するとカレントディレクトリ下に newcert.pem (認証局の署名が成されたクライアント証明書) が作成される。

(3) 作成した公開鍵と秘密鍵を PKCS#12 フォーマットに変換する
     cd /etc/pki/tls
     openssl pkcs12 -export -in newcert.pem -inkey newkey.pem -out yasushi_yamada.example.com.pfx
     /etc/pki/tls/misc/CA -sign
○ ここで入力するパスフレーズは、クライアント認証用のパスフレーズ のもの。

(4) 作成したクライアント証明書および秘密鍵をバックアップする
     cd /etc/pki/tls
     mkdir -p /etc/pki/dovecot/clients
     mv /etc/pki/tls/newcert.pem  /etc/pki/dovecot/clients/certs/yasushi_yamada.example.com.crt
     mv /etc/pki/tls/newkey.pem  /etc/pki/dovecot/clients/private/yasushi_yamada.example.com.key
     mv /etc/pki/tls/yasushi_yamada.example.com.pfx  /etc/pki/dovecot/clients/certs
     
○ 証明書を失効させる場合に必要 となるため、最低限、証明書のバックアップ は取っておく必要有。

2. 証明書管理のコツ

兎に角やってみると、どれが何だったか解からなくなってしまう(苦笑) これに自分のミスタイプやミス操作が加わると、中身が類似しているだけに一苦労である。このため、各証明書毎に介在するデータの形式をきちんと把握することと併せて、ある一定の運用を整えるのが得策と言える。

2.1 ファイルのフォーマット

(1) pem
pem 形式 のファイルとはなんぞや?pem とは、Privacy Enhanced Mail の略らしいが、要は、Base64 を使ったエンコーディング形式のことを示すらしい。SSL 絡みだと、秘密鍵は -----BEGIN RSA PRIVATE KEY----- 行に始まり、-----END RSA PRIVATE KEY----- 行に終わる base64 でエンコーディングされた文字列で表される。秘密鍵が、何らかの手段で暗号化されている場合は、-----BEGIN ENCRYPTED PRIVATE KEY----- 行に始まり、-----END ENCRYPTED PRIVATE KEY----- 行に終わる base64 のブロックの前に Proc-Type や DEK-Info などが挿入されている。
X509証明書の場合は -----BEGIN CERTIFICATE ----- 行に始まり、-----END CERTIFICATE----- 行に終わる base64 でエンコーディングされた文字列である。これらは全て PEM 形式である。

(2) crt ・ cer
では、crt 形式 とは?これ以外に cer という拡張子も同じ意味で使われるらしいが、これは、X509証明書を格納したものであることを示しているだけで、そのフォーマット自体には区別がないらしい。要は、pem 形式でエンコーディングされているものであっても、der 形式 (Distinguished Encoding Rules) と呼ばれる構文則で記述されているものであっても、内容がX509証明書であれば、crt あるいは cer といった拡張子が付与されていても問題ないようなのである。どうも、SSL の鍵絡みで混乱する要因のひとつは、ここにありそうである。

(3) crt
上記の crt 形式と同様、csr (Certificate Signing Request :署名要求) も同じように pem 形式でも der 形式でも、内容が署名要求であれば、csr という拡張子が使用されるようである。

【参考】 「技術/Security/PKI,,SSL,TLS/メモ01_拡張子の迷宮(pem,der,crt,cer,csr,…)」

2.2 ファイルを識別するコツ

こうなってくると如何にしてファイルを区別するかが重要なポイントになってくる。pem 形式の場合は、先頭と末尾の行で、そのデータが秘密鍵であるか、証明書であるかの区別は付く。しかし、証明書とあっても、その内容が不明である。

(1) CSR (証明書署名要求) かどうかを確認する方法
下記のコマンド "openssl req -in <check するファイル名> -verify -noout" を実行し、"verify OK" という結果が出れば csr ファイル。"unable to load X509 request" のような応答があったら 非 csr ファイル。

(2) CRT (X509証明書) かどうかを確認する方法
下記コマンド "openssl x509 -in <check するファイル名> -noout -subject" を実行し、subject= に続いてコモンネーム等が正常に表示されるようなら、crt ファイル。何かしらのエラーが生じるようであれば、それ以外のファイル。

(3) 秘密鍵 (key ファイル) と証明書 (crt ファイル)が同一の公開鍵のものであるかを確認する方法
秘密鍵より生成した公開鍵が、証明書に付与されている公開鍵と同一かどうかを確認する場合、下記コマンド "openssl x509 -in <証明書のファイル名> -pubkey -noout > tmp/file1.txt" および "openssl rsa -in <秘密鍵のファイル名> -pubout -out /tmp/file2.txt" を実行 (x509 と rsa とでは使えるオプションやコマンドの構文様式が若干異なることに注意) し、その出力結果である /tmp/file1.txt と /tmp/file2.txt を比較することで確認できる。"diff /tmp/file[12].txt" を実行し、差分が表示されれば、公開鍵は同一ではなく、差分がなければ同一のもの。

(4) X509証明書の内容を確認する方法
下記コマンド "openssl x509 -text -noout -in <証明書ファイル名>" を実行すると、Certificate: から始まる可読な構文形式で表示される。

(5) CSR (証明書署名要求) の内容を確認する方法
下記コマンド "openssl req -text -noout -in <署名要求ファイル名>" を実行する。

(6) 秘密鍵の内容を確認する方法
下記コマンド "openssl rsa -text -noout -in <秘密鍵ファイル名>" を事項する。

3. 参考資料

「プライベート認証局の証明書、サーバ証明書、クライアント証明書の作成方法について」
「TLS の設定」
「Apache + OpenSSL」
「無料の SSL 証明書 StartSSL を活用する」