もうちょっとちゃんとJavaでCSRを扱う
どうやら前ページのOpenSSLをコマンド呼び出しする実装ではいろいろと問題があるようなので,もうちょっとちゃんと実装してみた.
そもそも,CSRはDERというフォーマットか,それをBASE64エンコードしたPEMという形式でやりとりされる.
OpenSSLのコマンド
openssl req -noout -textは,内部でこれをデコードして文字列表現としていろいろなCSRの情報を出力してくれる. この「文字列表現」というところが曲者で,DNの値の型としては,文字列データではあるのだが,ASCIIだったり,UTF8だったり,EUC_JPなどだったりする. で,OpenSSLは,ASCII以外はうまく表示できるとは限らない. また,上記コマンドによるDNの文字列表現は,以下のような形式である.
C=JP, ST=SOMEWHERE, O=HOGE実はSTには"SOMEWHERE, O=HOGE"といった値も設定可能で,この場合C,ST,Oの設定なのか,C,STの設定なのかの判別は不可能となる. ということで,上記opensslコマンドはやはり人間向けであって,プログラムで厳密で細かい処理には向かない. PEM,DERをデコードする必要がある(※).
※ X509CertificateやX500Principalも,DER形式からnewできることから,内部でDERのデコードを行っているはずだが,何故かAPIは公開されていない.
ソースを入手するか,非公開APIなどを参照する.
前回のものを大幅に修正し(ほとんど作り直し),今回はCSRデータとしてDERかPEM形式のものを受け付け,それを解析するようにした.
以下処理シーケンス概要.
- PEM形式データはBASE64デコードしてDER形式とする.
- DER形式データをBER形式データ(DERはBERのサブセット仕様)として解析する. このときBERNodeツリーが作成される.
- BERNodeツリーから,CSRオブジェクトを作成する.
openssl asn1parse -i -in csr.pemで表示されるツリー上のデータ構造をJavaで表現したものである. DNの各項目は別々のノードにあり,各項目は型と値という二つのノードのペアになっている. このようなデータの保持方法だと,前項に揚げた問題を解決できる. DERやBERについては,よいページがほとんど見当たらないが,「ASN.1 バイナリ変換規則 (BER)」はかなり有用な情報が書いてあった. CSRDecoderTestというテストコードで,CSRのデコードに関するものは大体網羅されているが,例として一つここでも記述しておく.
FileInputStream is = new FileInputStream(testPEMFile);
CSRDecoder decorder = new CSRDecoder();
CSR csr = decorder.decodePEM(is);
assertEquals(0, csr.getVersion());
Name dn = csr.getDN();
assertEquals("JP", dn.getCountry().get(0));
assertEquals("SOMEWHERE", dn.getState().get(0));
assertEquals("SOMEWHERE-shi", dn.getLocality().get(0));
assertEquals("FIREPROJECT.JP", dn.getOrganization().get(0));
assertEquals("CSRDECODER", dn.getOrganizationalUnit().get(0));
assertEquals("TEST1", dn.getCommonName().get(0));
ファイルストリームから,PEM形式データを取り出してデコードする.
CSRDecoderのデコードメソッドには以下の4つがある.
- decodePEM(InputStream)
- decodePEM(String)
- decodeDER(InputStream)
- decodeDER(String)
作成したものをGPLのもとで配布する.
これ.
展開すると,fireproject.security.jarが出て来る.
これをCLASSPATHにいれると使用可能となる.
ソースとビルド環境も同梱されているので,修正作業なども行える.
JavaDoc作成方法は以下.
ant javadocこれでdoc/javadoc/にJavaDocが生成される. テスト実行にはまず,以下でライブラリを準備する.
$ ant preparelibこれでネットからjunitとtdocletをダウンロードする. これらは今回の成果物ではなく,それぞれにライセンスがあるので,各自確認されたい. テスト方法は以下.
ant test結果はdoc/testreport/html出力される.

