ファイヤープロジェクト
もうちょっとちゃんとJavaでCSRを扱う
2005-08-28T20:20+09:00   matsu
どうやら前ページの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形式のものを受け付け,それを解析するようにした. 以下処理シーケンス概要.
  1. PEM形式データはBASE64デコードしてDER形式とする.
  2. DER形式データをBER形式データ(DERはBERのサブセット仕様)として解析する. このときBERNodeツリーが作成される.
  3. BERNodeツリーから,CSRオブジェクトを作成する.
BERノードツリーは
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)
デコードすると,CSRオブジェクトが返るので,バージョンを取得したり,DN情報を取り出したりする. DN情報はNameオブジェクトにて表現している. 内部でBERNodeツリーを保持しており,国名や州などを取り出せる. あるキーに対して複数エントリ可能なので,各GetterはStringオブジェクトを格納したListオブジェクトを返す. Stringオブジェクトは,もとデータがUTF8やASCII文字列なら値が入っているが,それ以外なら""が返る.
作成したものをGPLのもとで配布する. これ. 展開すると,fireproject.security.jarが出て来る. これをCLASSPATHにいれると使用可能となる. ソースとビルド環境も同梱されているので,修正作業なども行える. JavaDoc作成方法は以下.
ant javadoc
これでdoc/javadoc/にJavaDocが生成される. テスト実行にはまず,以下でライブラリを準備する.
$ ant preparelib
これでネットからjunitとtdocletをダウンロードする. これらは今回の成果物ではなく,それぞれにライセンスがあるので,各自確認されたい. テスト方法は以下.
ant test
結果はdoc/testreport/html出力される.
matsu(C)
Since 2002
Mail to matsu