OpenSSLでの証明書管理
OpenSSLで証明書を作成する際の覚書です。
公開鍵と秘密鍵と証明書
公開鍵と秘密鍵は、「公開鍵暗号方式」の用語で、基本的に公開鍵と秘密鍵のふたつの鍵を使って暗号通信をするのに使います。
文字通り公開するための鍵が公開鍵で、秘匿する鍵が秘密鍵ですが、この鍵は片方の鍵でかけた暗号をもう一方の鍵で復号できるという仕組みになっています。
通信をする際は、送信者と受信者でそれぞれ秘密鍵と公開鍵を持ち、送信者は受信者の公開鍵で暗号化してデータを送ります。
署名はこれとは逆に、送信者が自分の秘密鍵で暗号化することを指します。秘密鍵で暗号化したものが、公開鍵で正規に復号できることがその証明となります。
証明書は署名の入った公開鍵の事を指します。
証明書周辺のファイルの種類
証明書や秘密鍵のファイルは、バイナリで保存されるDER形式と、Base64形式で保存されるPEM形式があります。
そのため、それらに付与される拡張子は、.der であったり .pem であったり環境によって違います。
また保存形式でなく役割を明示した拡張子の付け方だと、証明書(cert)を示す、.cer や .crt だったりすることもあります。
そのルールに基づいた場合、秘密鍵は key となるケースがあります。
その周辺では、署名を求める際に使う公開鍵を含んだ .csr 拡張子や、無効となった証明書リストを意味する .crl という拡張子などもあります。
CAの生成
OpenSSLでを管理をしようとする際、CA(証明機関)が必要になることが多いと思います。
CAは一連の証明書を発行する母体ですが、実態は公開鍵(証明書)と秘密鍵あとはいくつかのメタ情報のまとまりとなります。
同様に証明を受ける内容も特定の端末を識別するための情報です。
CAの場合でも、証明を受ける者も、それらのコアは秘密鍵です。
openSSLでCAを生成することができますが、作成したCAの信頼性を確保するためには、上位のCAにCAとしての証明書を発行してもらう必要があります。
閉じた環境での利用なら、自己署名という形で証明書を発行しCAを運用することもできます。
ここでは後者のパターンでCAを生成してみます。
openSSLでCAを生成するには、先の通り秘密鍵と公開鍵のセット、署名を作ればいいので、作り方のパターンはいくつかあります。この後示すのはその一例です。
CAの生成
# openssl req -newkey rsa:2048 -keyout ca.key -out ca.csrここでは、openssl の reqを 使って 署名要求(ca.csr)と同時にCAのコアとなる秘密鍵(ca.key)を生成しています。
秘密鍵はセキュリティ確保のため利用時のパスワードの設定を求められますが、これを省略したかったら -nodes(No DES) オプションを付けます。パスワードを設定すれば秘密鍵が漏洩した場合でも自由に使えないため保険として機能します。
証明書要求作成時には、CAとしての情報を入力します。
この中で重要なのはCommon Nameで、この情報で識別できるようにします。
- Country Name (2 letter code) [国]:JP
- State or Province Name (full name) [都道府県]:
- Locality Name (eg, city) [市町村]:
- Organization Name (eg, company) [組織]:
- Organizational Unit Name (eg, section) [部署]:
- Common Name (e.g. server FQDN or YOUR name) []:
- Email Address []:
ここで生成された署名要求(ca.csr)をルートCAなど上位のCAに署名してもらえば公的なCAとして機能しますが、ここでは次のようにして自分で署名します。
CAの自己署名
# openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crtx509 コマンドの -req オプションを指定してCSR(署名要求)から証明書を生成します。
-days オプションで有効期限を、-signkey で署名する鍵を、-out で出力する証明書を指定しています。
秘密鍵にパスワードを設定している場合は、コマンド入力後秘密鍵利用時のパスワードの入力を求められるので、入力します。
もし、-nodesオプションをつけずに作成した秘密鍵のパスワードを解除したい場合は、次のようにします。
秘密鍵のパスワード解除
# openssl rsa -in [入力ファイル名] -out [出力ファイル名]証明書の発行
今度は特定の端末用の証明書を発行します。CAが署名するのが自身の署名要求なのか、特定の端末用なのかが変わるだけで、自身の秘密鍵と公開鍵を作って署名要求を作る流れはCAと同じです。
署名対象(server)の生成
# openssl req -newkey rsa:2048 -keyout server.key -out server.csr今度は署名対象の情報を入力します。
署名対象の署名要求を、CAの秘密鍵で署名します(パスワードが設定してあればCA側のパスワードを追加入力します)。同じ署名ですが、自己署名をする際とは少しコマンドが変わります。
署名対象への署名
# openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt-CA で署名するCAの証明書、-CAkeyでその鍵を指定します。
-CAcreateserialは、証明書が一意になるようにするシリアル管理のためのファイルを生成するオプションです。初回署名時に必要で、2回目以降はこのオプションは指定しません。この場合、「 ca.srl 」というファイルが生成され、その中に発行した署名のシリアルナンバーが保存されます。シリアルナンバーは証明書に付与されているものと同値になります。
これで証明書の発行は終わりですが、このままの状態だと、秘密鍵が漏洩した場合それを持っている者に証明の権威の移行してしまいます。その可能性を低くするために、紹介するように、証明書に追加の情報を加えます。
バージョン3署名
追加情報は、要求時にそれを要求することはできますが、署名時に証明書に明示して組む必要があります。逆に要求がなくても付与することができます。
近年のブラウザでは先の状態では意図したように証明書が機能しないため、それに対応することを目的とすると、主に次のような追加の項目が必要です。
これらはテキストファイルとして保存し、署名時に利用します。
オプションファイル
basicConstraints=CA:FALSE subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer keyUsage= nonRepudiation, digitalSignature, keyEncipherment subjectAltName=IP:192.168.0.1
これらの設定を説明すると次のようになります。
- basicConstraints=CA:FALSE
この項目ではCAではないことを示しています。
- subjectKeyIdentifier=hash
subjectは証明書主体(証明書内で証明を受ける者)を指します。その識別子を証明書のハッシュ(hash)としています。
- authorityKeyIdentifier=keyid,issuer
証明書を発行したCA識別子を、keyid,issuerとしています。
keyidは公開鍵の識別子を意味し、発行CAの公開鍵のハッシュ値を指します。あわせて、発行者も識別子として扱います。
先のhashは証明書全体を対象とするのに対し、keyidは公開鍵の部分のみをhashとする違いがあります。
- keyUsage= nonRepudiation, digitalSignature, keyEncipherment
keyUseageでは公開鍵の使い道を指定しています。nonRepudiationは送信者が後でその送信を否定するのを防ぎます。
防ぐといっても実際になにかロジックを持って機能するわけではなく、「 社外秘 」や「 confidential 」といったようなドキュメントの格を上げるために用いるものです。
digitalSignature は電子署名、 keyEncipherment は暗号化の意味です。
- subjectAltName=IP:192.168.0.1
subject(証明主体の) Alternative Nameの意味で、追加の識別子を設定します。近年のブラウザはこれにより判定サーバーの判定をするようです。IPアドレスで指定するなら IP: プレフィックスの後にIPアドレス、ドメインなら DNS: プレフィックスの後にドメインを入力します。
こうして作成したオプションファイルを使用して署名をするには次のようにします。
署名対象への署名
# openssl x509 -req -days 365 -in server.csr -signkey ca.key -out server.crt -extfile [ファイルへのパス]CA用にバージョン3の情報を含める際は、keyUsage を 「 keyCertSign, cRLSign 」として署名目的に変える必要がある他、失効リストを配布する場所を示す、CRL Distribution Points などを加えることになると思います。
また、作法的に正しいかどうか不明ですが、次のような、Webサーバー用の署名とルートCAを混在させたバージョン3署名を自己署名に加えることもできました。
option.v3
basicConstraints=CA:TRUE subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer keyUsage= nonRepudiation, digitalSignature, keyEncipherment, keyCertSign, cRLSign subjectAltName=IP:[WebサーバーのIPアドレス]
証明書の表示や確認
OpenSSLを使って作成した証明書の確認をするには次のようにします。
証明書の表示
# openssl x509 -in [証明書ファイル] -text -noout-textは可読化(Base64から自然言語化)する指示です。また、-noout は出力を止めるオプションで、これを指定しない場合は可読化されたテキストの後に再度証明書の生データが出力されます。
もしファイルが バイナリ(.der)形式なら、-inform DER を加えます。
証明書の表示
# openssl x509 -in [証明書ファイル(.der)] -inform DER -text -noout証明書を検証するには、verify コマンドを使います。
これは証明書チェーンをたどって、指定された証明書が有効かどうかチェックするものです。信頼できるかどうかのチェックとなりますので、任意に生成した自己署名のCAに対してはすべてエラーとなります。
証明書の検証
# openssl verify [証明書ファイル(.crt)] # 自己署名CAの証明書を対象にした場合 error 18 at 0 depth lookup: self-signed certificate error ca.crt: verification failed # 自己署名CAから署名を受けた証明書を対象にした場合 error 20 at 0 depth lookup: unable to get local issuer certificate error server.crt: verification failed