2019/03/01(金)ディジタル証明書の形式 pem と der
2019/03/01 18:15
※現在、実運用で使っていませんが念のため一部端折っています。
-----BEGIN CERTIFICATE----- MIIC4TCCAkqgAwIBAgIBADANBgkqhkiG9w0BAQUFADB4MQswCQYDVQQGEwJKUDER MA8GA1UECBMISG9ra2FpZG8xGzAZBgNVBAoTEkJhc2UgS2VybmVsIENvIEx0ZDEg MB4GA1UECxMXTmV0d29yayBPcHJhdGlvbiBDZW50ZXIxFzAVBgNVBAMTDkJhc2Ug S2VybmVsIENBMB4XDTA4MDcxMzEzMTU0NVoXDTI4MDcxMzEzMTU0NVoweDELMAkG ・・・・一部省略・・・・ A1UEBhMCSlAxETAPBgNVBAgTCEhva2thaWRvMRswGQYDVQQKExJCYXNlIEtlcm5l +6EEruiOlNKYnViRTdjEoAPRYfgM+eqjnfbVOxB0wEV7w5GjcqbGe9ePrEUs1wYS ktnZC7H0p5H01z92udKE3BaCEACQ -----END CERTIFICATE-----これは、pem 形式と呼ばれるディジタル証明書で、通常はこの形式で管理します。
ところが、時々、 der 形式しか受け付けないディジタル証明書アプリケーションがあるのです。
今回、コントロールパネルのサーバ設定部分の一部が時代に合わなくなっていて、この部分の改良を施しているところで、その一環でサーバ証明書をある程度自力管理できるようにしているのですが、その過程でディジタル証明書の内容を解析する Perl モジュールに Crypt::X509 という便利なものがあってそれを使おうとしたら、このモジュールが der 形式しか対応していないのです。
もっと便利そうなものに Crypt::OpenSSL::X509 というのがあるが、今のところ、OpenSSL 1.x 系への対応があまり芳しくなく、避けざるを得ない状況。
der 形式はバイナリファイルなので扱いにくいのです。ただ、具体的中身まではよく知りません。
調べると、 pem 形式ファイルの -----BEGIN CERTIFICATE----- 行と、-----END CERTIFICATE----- 行を取っ払った残りの部分を、Base64 デコードしてあげればいいだけであることが判りました。
つまり、pem 形式は、der 形式で生成したディジタル証明書のデータ構造を Base64 エンコードして、-----BEGIN CERTIFICATE----- 行と、-----END CERTIFICATE----- 行を付け足しただけなのです。
ここまで判れば、ディジタル証明書の内容確認は、Perl でやる場合は以下の要領で出来ます:
#!/usr/local/bin/perl use MIME::Base64 ; # Base64ライブラリ使用宣言 use Crypt::X509 ; # 証明書内容参照ライブラリ使用宣言 $csr_pem = "" ; $status = open (CSRPEM,"hoge.pem") ; if ($status) { local $/ = undef ; $csr_pem = <CSRPEM> ; close(CSRPEM) ; } $csr_pem =~ /\-\-\-\-\-BEGIN\s+CERTIFICATE\-\-\-\-\-(.+)\-\-\-\-\-END\s+CERTIFICATE\-\-\-\-\-/s ; $x509_tmp = $1 ; %outstr = {} ; $x509_decode = Crypt::X509->new(cert => decode_base64($x509_tmp)) ; @nb = localtime($x509_decode->not_before) ; @na = localtime($x509_decode->not_after) ; @jw = ('日','月','火','水','木','金','土') ; $outstr{'not_before'} = sprintf("%d/%02d/%02d(%s) %02d:%02d:%02d",$nb[5] + 1900,$nb[4] + 1,$nb[3],$jw[$nb[6]],$nb[2],$nb[1],$nb[0]) ; $outstr{'not_after'} = sprintf("%d/%02d/%02d(%s) %02d:%02d:%02d",$na[5] + 1900,$na[4] + 1,$na[3],$jw[$na[6]],$na[2],$na[1],$na[0]) ; $outstr{'subj_country'} = $x509_decode->subject_country ; $outstr{'subj_state'} = $x509_decode->subject_state ; $outstr{'subj_local'} = $x509_decode->subject_locality ; $outstr{'subj_org'} = $x509_decode->subject_org ; $outstr{'subj_ou'} = $x509_decode->subject_ou ; $outstr{'subj_cn'} = $x509_decode->subject_cn ; $outstr{'issuer_cn'} = $x509_decode->issuer_cn ; $serial16 = sprintf("%X",$x509_decode->serial) ; $serial16 = '0' . $serial16 if (length($serial16) % 2) ; 1 while $serial16 =~ s/^([\da-fA-F]+)([\da-fA-F][\da-fA-F])/$1\:$2/ ; $outstr{'issuer_serial'} = $serial16 ; $outstr{'issuer_country'} = $x509_decode->issuer_country ; $outstr{'issuer_state'} = $x509_decode->issuer_state ; $outstr{'issuer_local'} = $x509_decode->issuer_locality ; $outstr{'issuer_org'} = $x509_decode->issuer_org ; $outstr{'sigalgo'} = $x509_decode->sig_algorithm ;上記サンプルにて、連想配列 %outstr に表示可能な文字列にて解析内容が入ります。
参考:https://metacpan.org/pod/Crypt::X509