まず、Symantec(旧Verisign)などに署名された正式な証明書を実装する場合の手順。昨今では、やれキー長は 2048 bit以上でなきゃだめだの、ハッシュアルゴリズムは SHA1 ではもう弱いだのと五月蠅い。389 Directory Serverのページなどで GnuTLS Utilsを使うやり方を紹介したが、時代に追いついていく気がないらしく、どうもウマくないので、OpenSSL に立ち戻ることにした。
Apache専用のキー管理ディレクトリを作らなければならない必然性はないが、整理整頓の意味で専用のツリーを作ることにする。
プライベートキーの生成
# cd /etc/pki/ # mkdir apache && cd apache # mkdir private certs # cd private # openssl genrsa -des3 -out server.key 2048 Enter pass phrase: <-パスフレーズ入力。ちゃんと覚えておくこと-> # openssl rsa -text -noout -in server.key <-内容確認 # chmod 600 server.key
CSRの作成
※ -sha256オプションについては、例えば Symantec-Verisignでは「不要」と注意書きがしてあったりする。CAの公開している手順書の確認が必要である。
# openssl req -new -key server.key -out server.csr -sha256 Enter pass phrase for server.key: <-プライベートキーのパスフレーズ入力-> <-Contry-code, State or Province(県名), Locality(市町村名), O(団体名), OU(部署), CN(公開ServerのFQDN)など入力-> # openssl req -text -noout -in server.csr <-内容確認
server.csr を商用CAに送り署名してもらう。
送り返されてきた署名済み証明書全文("--BEGIN CERTIFICATE--"から"--END CERTIFICATE--"までそれらも含めて) をテキストにペースト。基本的にはLF改行で保存。ファイル名は任意だが例として server.crt として保存したとする。
最近は2段階式の中間証明書チェーンが一緒に必要。証明書の案内に書かれたURLからコピペして、これもテキストに保存。2段階それぞれの"--BEGIN CERTIFICATE--"から"--END CERTIFICATE--"までをそれらも含めてひとつのテキストファイルに保存。ファイル名は任意だが例として caintchain.crt に保存したとする。
これらをWebサーバマシンに保存。
/etc/pki/apache/ \_ certs/ \_ server.crt root:apache 640 caintchain.crt root:apache 640
ApacheのSSLコンフィグインクルードファイル(通常なら/etc/httpd/conf.d/ssl.conf) の以下の箇所を編集。
SSLCertificateFile /etc/pki/apache/certs/server.crt SSLCertificateKeyFile /etc/pki/apache/private/server.key SSLCertificateChainFile /etc/pki/apache/certs/caintchain.crt SSLPassPhraseDialog exec:/etc/httpd/conf/passtool
上記最終行は、httpdの起動時にサーバプライベートキーのパスフレーズを自動入力させるための仕掛け。次のような /etc/httpd/conf/passtool スクリプトを作る。
#!/bin/sh -- if [ "$1/$2" = "servername.com:443/RSA" ]; then echo mypassphrase exit 0 fi exit 0
パーミッションで保護。root:root 700 に。httpd はSSLサイト毎に "SERVERNAME:PORT ", "ENC"(DSA,RSA,ECCのいずれか) を第1,第2引数として渡してくるので、if 文でそれを確認してから出力するようにしている。
ちなみに、最近はSSLv2も穴があってダメだとか世知辛い世の中。SSL設定ファイルの SSLCipherSuite ディレクティブで、許容するサイファースペックを絞り上げておいたほうがよい。例えば ここ によると、
互換性重視なら、
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-GCM-SHA256:\ AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:\ ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA256:\ DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:\ AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:\ !aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4
より厳しい規制なら、
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
がよろしかろう、だそうだ。前記はMozillaの推奨を元にしているという記述があり、Mozilla Wki に現在載っている基本的互換性仕様は、
SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:\ ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\ DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:\ ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:\ ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:\ DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:\ AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
モダンな設定は、
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:\ ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\ ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
となっている。いずれにしろ寿限無じゅげむであり精査している暇がない。
テスト目的や、閉鎖系に近い小規模なネットワーク内で、お金をかけずにApacheを少しでもまともにSSL化するなら、プライベートCAという手もある。
私設認証局を立てる。Apacheの乗っているマシンでも別でもどちらでも構わないが、Webサーバは DMZ にあることが多く、何をされるか分からないので、安全なセグメントにある別のマシン上に開設する方が妥当だろう。検証は CentOS 6 で行った。
まず、/etc/pki/tls/openssl.cnf を修正する。変更点を示す。テキストファイルはこちら。
--- openssl.cnf.org 2016-02-24 23:45:46.000000000 +0900 +++ openssl.cnf 2016-03-19 21:57:59.000000000 +0900 @@ -70,9 +70,9 @@ # crlnumber must also be commented out to leave a V1 CRL. # crl_extensions = crl_ext -default_days = 365 # how long to certify for +default_days = 3650 # how long to certify for default_crl_days= 30 # how long before next CRL -default_md = default # use public key default MD +default_md = sha256 # use public key default MD preserve = no # keep passed DN ordering # A few difference way of specifying how similar the request should look @@ -85,7 +85,7 @@ countryName = match stateOrProvinceName = match organizationName = match -organizationalUnitName = optional +organizationalUnitName = supplied commonName = supplied emailAddress = optional @@ -104,7 +104,7 @@ #################################################################### [ req ] default_bits = 2048 -default_md = sha1 +default_md = sha256 default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes @@ -127,25 +127,25 @@ [ req_distinguished_name ] countryName = Country Name (2 letter code) -countryName_default = XX +countryName_default = JP countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) -#stateOrProvinceName_default = Default Province +stateOrProvinceName_default = Aichi localityName = Locality Name (eg, city) -localityName_default = Default City +localityName_default = Nagoya 0.organizationName = Organization Name (eg, company) -0.organizationName_default = Default Company Ltd +0.organizationName_default = Hoge Net # we can do this but it is not needed normally :-) #1.organizationName = Second Organization Name (eg, company) #1.organizationName_default = World Wide Web Pty Ltd organizationalUnitName = Organizational Unit Name (eg, section) -#organizationalUnitName_default = +organizationalUnitName_default = Information Tech commonName = Common Name (eg, your name or your server\'s hostname) commonName_max = 64 @@ -187,7 +187,7 @@ [ usr_cert ]ブロックの中(CAでCSRに署名する際に使われる) # nsCertType = client, email, objsign # This is typical in keyUsage for a client certificate. -# keyUsage = nonRepudiation, digitalSignature, keyEncipherment +keyUsage = nonRepudiation, digitalSignature, keyEncipherment # This will be displayed in Netscape's comment listbox. nsComment = "OpenSSL Generated Certificate" @@ -244,7 +244,7 @@ [ v3_ca ]ブロックの中(CA操作時に使われる) # Key usage: this is typical for a CA certificate. However since it will # prevent it being used as an test self-signed certificate it is best # left out by default. -# keyUsage = cRLSign, keyCertSign +keyUsage = cRLSign, keyCertSign # Some might want this also # nsCertType = sslCA, emailCA
nsCertType やその類はNetscape時代の遺物であり、現代では使うアプリケーションがほぼないらしく、頓着無用だ。
/etc/pki/tls/misc/CA スクリプトを改造 (diff)。後に述べる Client認証キー用ルーティンの追加を含む、というより大部分がそっちだ。
ついでに Perlスクリプト版 も作ってみた。GitHub から最新の CA.pl を拾ってきたのだがかなりテリブルだったので跡形がないほどに改造した。
CAのプライベートキーと自己署名済みパブリックキーの生成。
# ./CA -newca # cd /etc/pki/CA # openssl req -text -noout -in careq.pem <-内容確認 # openssl x509 -text -noout -in cacert.pem <-内容確認
ブラウザでのインポート用に公開鍵のフォーマットを変換。
# openssl x509 -in cacert.pem -inform pem -out cacert.crt -outform der # openssl x509 -text -noout -in cacert.crt -inform der <-内容確認
サーバ秘密鍵とCSRの作成。CAスクリプトで -newreq してもいいのだが、この用法においては openssl コマンドを直接打ってもそう込み入ってはいないので、直接コマンドでやることにする。
# cd /etc/pki/tls # mkdir apache && cd apache # mkdir private certs # cd private # openssl genrsa -des3 -out server.key 2048 <-プライベートキー生成 # openssl rsa -text -noout -in server.key <-確認 # openssl req -new -key server.key -out newreq.pem -sha256 <-CSR作成 # openssl req -text -noout -in newreq.pem <-確認
プライベートCAによるサーバCSRへの署名。
# /etc/pki/tls/misc/CA -sign # openssl x509 -text -noout -in newcert.pem <-確認 # mv newcert.pem ../certs/server.pem # rm newreq.pem
server.key を Webサーバの /etc/pki/apache/private/ へ、server.pem を /etc/pki/apache/certs/ へ、CAのパブリックキー /etc/pki/CA/cacert.pem を /etc/pki/CA/ へコピーする。
/etc/httpd/conf.d/ssl.conf の指定箇所。
SSLCertificateFile /etc/pki/apache/certs/server.pem
SSLCertificateKeyFile /etc/pki/apache/private/server.key
SSLCertificateChainFile /etc/pki/CA/cacert.pem
#SSLCACertificateFile <-cacert.pemはこちらに書いてもよいがクライアント認証用にあけておく
クライアントPCに cacert.crt をコピーし、ブラウザで「認証局証明書」ストア (IEだと「信頼されたルート証明機関」) にインポートする。
プライベートCAで署名したクライアントキーによって、鍵を持っているクライアントしかサイトにアクセスできないようにする。もちろん、プライベートCAをまだ開局していない場合は先に作っておくこと。
/etc/pki/tls/openssl.cnf を雛形にして openssl-webclient.cnf を作成。オリジナルファイルとの diff を示す。
--- openssl.cnf.org 2016-02-24 23:45:46.000000000 +0900 +++ openssl-webclient.cnf 2016-03-19 16:29:32.000000000 +0900 @@ -70,9 +70,9 @@ # crlnumber must also be commented out to leave a V1 CRL. # crl_extensions = crl_ext -default_days = 365 # how long to certify for +default_days = 730 # how long to certify for default_crl_days= 30 # how long before next CRL -default_md = default # use public key default MD +default_md = sha256 # use public key default MD preserve = no # keep passed DN ordering # A few difference way of specifying how similar the request should look @@ -85,7 +85,7 @@ countryName = match stateOrProvinceName = match organizationName = match -organizationalUnitName = optional +organizationalUnitName = supplied commonName = supplied emailAddress = optional @@ -104,7 +104,7 @@ #################################################################### [ req ] default_bits = 2048 -default_md = sha1 +default_md = sha256 default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes @@ -127,25 +127,25 @@ [ req_distinguished_name ] countryName = Country Name (2 letter code) -countryName_default = XX +countryName_default = JP countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) -#stateOrProvinceName_default = Default Province +stateOrProvinceName_default = Aichi localityName = Locality Name (eg, city) -localityName_default = Default City +localityName_default = Nagoya 0.organizationName = Organization Name (eg, company) -0.organizationName_default = Default Company Ltd +0.organizationName_default = Hoge Net # we can do this but it is not needed normally :-) #1.organizationName = Second Organization Name (eg, company) #1.organizationName_default = World Wide Web Pty Ltd organizationalUnitName = Organizational Unit Name (eg, section) -#organizationalUnitName_default = +organizationalUnitName_default = Information Tech commonName = Common Name (eg, your name or your server\'s hostname) commonName_max = 64 @@ -187,7 +187,7 @@ <-[ usr_cert ]ブロック # nsCertType = client, email, objsign # This is typical in keyUsage for a client certificate. -# keyUsage = nonRepudiation, digitalSignature, keyEncipherment +keyUsage = nonRepudiation, digitalSignature, keyEncipherment # This will be displayed in Netscape's comment listbox. nsComment = "OpenSSL Generated Certificate" @@ -214,7 +214,7 @@ #nsSslServerName # This is required for TSA certificates. -# extendedKeyUsage = critical,timeStamping +extendedKeyUsage = clientAuth [ v3_req ] @@ -244,7 +244,7 @@ <-[ v3_ca ]ブロック # Key usage: this is typical for a CA certificate. However since it will # prevent it being used as an test self-signed certificate it is best # left out by default. -# keyUsage = cRLSign, keyCertSign +keyUsage = cRLSign, keyCertSign # Some might want this also # nsCertType = sslCA, emailCA
最初だけ、ディレクトリ構造を作らせるためにダミーのキーを一式作成する。
# cd /etc/pki/tls/misc # ./CA -newwebclient client0 (-newwebclientはCAスクリプトの改造で加えたルーティン) <中略> Enter Export Password: <入力> Verifying - Enter Export Password: <再入力> # ls -lR /etc/pki/webclient
# openssl ca -revoke /etc/pki/webclient/certs/client0.pem Enter pass phrase for /etc/pki/CA/private/cakey.pem: <入力> Revoking Certificate XXXXXXXXXX. Data Base Updated # rm /etc/pki/webclient/*/client0.*
PKCS#12キーバッグ(Client秘密鍵とCA署名済みClient公開鍵の合成物)作成時のエクスポートパスワード入力を省くためのパスワードファイルを配置する。内容はパスワード文字列 1行のみ。
# echo 'exportpassword' >/etc/pki/webclient/private/exportpw # chmod 600 /etc/pki/webclient/private/exportpw
# cd /etc/pki/tls/misc # ./CA -newwebclient client1 (引数は整理のためのクライアント名で、ファイル名に使われる) <中略> Country Name (2 letter code) [JP]: State or Province Name (full name) [Aichi]: Locality Name (eg, city) [Nagoya]: Organization Name (eg, company) [Hoge Net]: Organizational Unit Name (eg, section) [Information Tech]: Common Name (eg, your name or your server's hostname) []:client1 <-後々管理の糸口となるので必ず入力 Email Address []: <中略> Keys generated successfully: /etc/pki/webclient/certs/client1.pem Client public key(signed) /etc/pki/webclient/private/client1.key Client private key /etc/pki/webclient/private/client1.p12 Client PFX(above two combined)<-実際必要なのはこれ /etc/pki/CA/cacert.crt Private-CA public key <-この時作られるわけではないが参考のためプリントさせている
なお、RHEL/CentOS 6 に付属しているシェルスクリプト版CAスクリプトの、もともと持っている機能として、環境変数による挙動切り替え機能がある。
# DAYS="-days 180" ./CA -newwebclient client1
とやると、署名後のクライアント公開鍵の有効期限は、openssl-webclient.cnf の default_days やCAスクリプト序盤で定義しているDAYSを無視して、180 日になる。また、
# SSLEAY_CONFIG="-config /PATH/TO/ALT_OPENSSL.cnf" ./CA -newwebclient client1
とやれば、使用する openssl設定ファイルを一時的に切り替えることができる。同様な仕掛けの環境変数としては他に OPENSSL (既定値=openssl) と CATOP (既定値=/etc/pki/CA) があり、今回の大改造に伴い更に CERTTOP (既定値=/etc/pki/webclient) を付け加えた。
Perl版もだいたい同じ。ただし、-revoke の代わりに -revoke-webclient (ベースにしたCA.pl は既に汎用的な -revoke ファンクションを持っていたため)、環境変数 SSLEAY_CONFIG の代わりに OPENSSL_CONF となっている。
# cd /etc/pki/CA # cp -p index.txt index.txt.bak # : >index.txt <-'cat /dev/null >index.txt'でも何でもとにかくトランケートできればよし
CAのパブリックキー /etc/pki/CA/cacert.pem を Webサーバの /etc/pki/CA/ へコピーしておく。
/etc/httpd/conf.d/ssl.conf の修正箇所は以下。
SSLCACertificateFile /etc/pki/CA/cacert.pem <LocationMatch "^/(?!(manual|server-info|server-status|balancer-manager))"> SSLVerifyClient require SSLVerifyDepth 10 </LocationMatch>
実際的にはクライアント認証なしでアクセスしたいパスやロケーションがあると思うので、LocationMatch で特定のURIを除外する否定の前方参照正規表現の例を書いてみた。
クライアントPCに、cacert.crt (CAパブリックキーのDERフォーマット版) と client1.p12 をコピーする。cacert.crt をブラウザの「認証局証明書」(IEだと「信頼されたルート証明機関」) ストアにインポートする。そして、client1.p12 を (FireFox系)「あなたの証明書」ストア、(IE)「個人」ストアにインポートする。インポートの際に入力するのは exportpw に書いたパスワードだ。
管理を少しでもラクにするよう、CAスクリプトには、発行済みキーセットのリヴォークと削除をするルーティンも取り入れた。初めてのリヴォークを実行する前には、まず、CRLナンバーをカウントアップするためのシリアルファイルを作っておかなければいけない。失効シリアル番号は発行キーのシリアルと桁数を合わせた方がいいと書いているサイトもあるので、気になる人は同ディレクトリにある serial ファイルをコピーしてもいいかもしれない。
# echo 01 >/etc/pki/CA/crlnumber
そうしておいてから、
# ./CA -revoke client1 Using configuration from /etc/pki/tls/openssl.cnf Enter pass phrase for /etc/pki/CA/private/cakey.pem: <入力> Revoking Certificate XXXXXXXXXXXXXX. Data Base Updated Using configuration from /etc/pki/tls/openssl.cnf Enter pass phrase for /etc/pki/CA/private/cakey.pem: <再度入力> rm: remove 通常ファイル `/etc/pki/webclient/certs/client1.pem'? y rm: remove 通常ファイル `/etc/pki/webclient/private/client1.key'? y rm: remove 通常ファイル `/etc/pki/webclient/private/client1.p12'? y CLIENTID client1 successfully revoked
CA秘密鍵のパスフレーズを2回訊かれるのは、失効キーリストファイル(CRL)の更新もしているから。リヴォーク自体とリストの更新は一息に
openssl ca -revoke /PATH/TO/client1.pem -gencrl -out ${CATOP}/crl/crl.pem
という風にできると述べているサイトもあるのだが、そうすると、失効リストへは次回からしか反映されない。そのため仕方なく、ca を -revoke と `-gencrl -out' の2回に分けて呼んでいるので計2回出るわけだ。バージョンによる違いだろうか(検証環境のopensslパッケージは 1.0.1e-42)。
この項はオプションであって、やらなくてもクライアント認証が成り立たないわけではない。しかし、PKCS#12 キーは一応インポート用パスワードで保護されているとはいえ、ユーザを通じて悪意を持って再配布されたり、遠隔モニタウィルスによってキーとパスワードがセットで流出しないとも限らないので、「破棄してくれ」と言って従ってくれる場合ばかりとは限らないのだ。CRLをApacheで活用すれば、失効したキーをインストールしたブラウザはサイトを表示することができなくなる。OpenSSLのリヴォーク情報は勝手にApacheに伝わってはくれない。そのための設定が必要だ。序盤にも述べたように、安全性に鑑みて、CAマシンとWebサーバは別立てだとして話を進める。
関係するディレクトリおよびファイル。
CAマシン側:
/etc/pki/ \_ CA/crl/ crl.pem <-CAスクリプトでの`ca -gencrl -out'で作られる失効情報ファイル \_ webclient/ Makefile <-crl.pemファイルをWebサーバへ送るための仕掛け (root:root 600)
Makefileの内容:
crldir = /etc/pki/CA/crl httpserver = centos6u httpcrldir = /etc/httpd/conf/crl syncuser = root SSH := /usr/bin/ssh -l $(syncuser) -i /root/.ssh/id_rsa .PHONY: sync sync: $(crldir)/crl.pem /usr/bin/rsync -c --rsh="$(SSH)" $< \ $(syncuser)@$(httpserver):$(httpcrldir)/ && \ $(SSH) $(httpserver) \ "cd $(httpcrldir) && make"
Webサーバ側:
/etc/httpd/conf/ \_ crl/ <-root:rootで作っておく crl.pem <-CAマシンから同期転送される xxxxxxxx.r0 <-crl.pemへのシンボリックリンク Makefile <-リンクの更新とApacheのリロードをするための仕掛け (root:root 600) tstamp.t0 <-makeの都合で使うダミーファイル
Makefileの内容:
crl = crl.pem linkname = $(shell openssl crl -hash -noout -in $(crl)).r0 tstamp = tstamp.t0 $(tstamp): $(crl) find . -type l -name *.r0 -exec rm -f '{}' ';' ln -s $(crl) $(linkname) /sbin/service httpd graceful -@touch $(tstamp)
早い話が、
というカラクリだ。見ての通り、Webサーバ側での`make'はCA側での`make'の中からキックされるので、特に事情のない限りWebサーバで make を直接コールする機会はない。CAでの make の際に、何の仕掛けもしないとrootのパスワードを何度も聞かれてしまい自動化できないので、CAマシン側のrootユーザからWebサーバ側rootへのssh非対称鍵を配備しておく必要がある (sshdのページを参照)。
そして肝心のApacheの設定。ssl.conf に下記の1項目を加える。前述の SSLVerifyClient とは異なり <Directory> や <Location> ブロック等には入れられないことに注意。
SSLCARevocationPath conf/crl
これで準備はOK。`./CA -revoke client1' といった具合にキーを失効をさせたら、続いてCAマシン上で、
# cd /etc/pki/webclient # make
これにて反映完了。client1用キーを持ったブラウザからはサイトにアクセスできなくなったはずだ。さらに楽チンにするなら、前述のカスタムCAスクリプト差分の末尾付近にある "cd ${CERTTOP} && make" のコメントを外してもらえば、make は `CA -revoke ...`の終わりに勝手にトリガーされる。
/etc/pki/webclient 配下からキーセットを消してしまっても、CAの newcerts ディレクトリに公開鍵のコピーが <SERIAL>.pem のファイル名で蓄積されている。キーの Common Name(CN) とシリアルとの対応は index.txt に載っているので、
# grep client1 /etc/pki/CA/index.txt V 180319175891Z AB25B339750E086 unknown /C=JP/ST=Aichi/O=Hoge Net/OU=Information Tech/CN=client1
といった具合に検索できる。 ちなみに、第1フィールドは V=valid/R=revoked, 第2は有効期限のYYMMDDHHMMSSZ, 第3(上記では失効していないので空)が失効日時, 第4がシリアル, 第5はキーファイル名または"unknown", 最後の第6は言うまでもなくDN。よって、
# openssl ca -revoke /etc/pki/CA/newcerts/AB25B339750E086.pem # openssl ca -gencrl -out /etc/pki/CA/crl/crl.pem
とやればリヴォークできる。CA/newcerts にさえ既にない場合でも、*.p12 ファイルさえ手に入れば、そこから公開鍵を取り出して失効させることは可能だ。-nodes オプションは「取り出す時に公開鍵を暗号化しなくてよい」の意:
# openssl pkcs12 -in clientX.p12 -clcerts -nodes -out clientX.pem Enter Import Password: <Exportパスワードを入力> MAC verified OK # ls *.pem clientX.pem <-あとはこれを入力にして失効させればよい
度重なるテストで失効済みキーだらけになったCAを掃除する手順。配布済みのクライアントキーを全部回収してからやらなくてはいけない。配布済みキーは二度とリヴォークできなくなるので、実運用中のCAでは基本的に御法度。キーとCRLのシリアルカウンターは放っておくの得策。
# cd /etc/pki/CA # cat /dev/null >index.txt <-テキストデータベースをトランケート # rm -f newcerts/*.pem <-今までに発行したクライアント公開鍵のコピーを全削除 # rm crl/crl.pem <-失効キーリストの削除。次回revoke操作時にまた新たに作られる