top / index / prev / next / target / source

2000-09-20 diary: JSSE 1.0.2 ハマり中 -> 解決

いがぴょんの日記 日記形式でつづる いがぴょんコラム ウェブページです。

old-v2

JSSE 1.0.2 ハマり中 -> 解決

いがぴょんの日記v1 (旧称: ある開発者の日記) から移植しました。

SUN Java Secure Socket Extension (JSSE) で ちとハマってます

とある業界の B2B を XMLトランザクション実装する仕事を実装しています。(2007.08.12一部変更 現在の価値観に従い、表現を一部変更しました。) Mime Base64 とか 圧縮・伸張とかは難なくクリアーできたのですが、根っこのセキュリティ部分でハマってます。HTTP on SSL (つまりは https) の箇所です。

基本的に SUN Java Secure Socket Extension (JSSE) 1.0.2 ベースで考えています。これは まぁ妥当であろうと思えます。ところが、なぜか JSSE 1.0.2 付属のサンプルではうまく動作しなかったりするためです。(URLConnectionに https を渡すスタイルのサンプル) Microsoft Internet Explorer5.0 では httpsベースで接続できているので、サーバ側の設定ミスでは無い模様です。(ってことはクライアント側の設定や何かお膳立てが抜けているんでしょうねぇ)現在、適当な資料や講習会を知りたく 探しているところです。メサキ的には『動く』サンプルソースコード(及びその設定)が載っかっているウェブページなど見つかれば良いのですが、、、。どなたか ご存じの方、一発突っ込みを入れていただけませんでしょうか?ウェブページの場合 英語でもOKです。(ドイツ語とかイタリア語とかはちょっとダメです) (というか ごく初歩的な クライアント側の設定ミスであるようにも思えるので、余計に恐縮です)詳しい方、、、ど~ぞよろしく お願いいたします。

2000/09/20 師匠に

を教えてもらいました。うう~ん (苦笑)

2000/09/20 読者群からの『どと~』な突っ込み群

件名:JSSEの情報についていがびょん様、はじめまして、M.Yと申します。いつも楽しく日記を読ませて頂いています。今日の日記にJSSEについての記述があり、資料を探しているとのことでしたのでメールさせていただきました。私が知っているのは、Java WORLDの 2000.4月号にJSSEの記事が載っています。 Java API徒然草 第十六段にJSSEの紹介がされています。私自身、この記事を参考にHTTPSによるWebへのアクセスをするJavaクライアントを作成し、成功しています。毎日日記を読ませて頂いており、非常に勉強になっています。何かおかえしをしたくメールさせて頂きました。#きっと他にもたくさんの人からリプライがあるかもしれませんが、重複してたらすみません。これからも日記を楽しみにしています。

このメールを載せるときは匿名でお願いいたします。 --

別の方からのお便り

件名:JSSE についてbataと申します。※2回目の登場となるかと思いますが・・・前回はNotesの時だったと思います。では、本題にはいって・・・ JSSEのクライアント動作ですがこれはSSLの動作どうりなのですが、ドキュメントに詳しくかかれていないのでみなさんの悩み所 だと思います。IEの場合、SSL通信発生時にダイアロクが表示されると思いますがこの時、サーバから証明書が送られてきています、このダイアロクで証明書の確認をしています。OKの場合、この証明書を認証したとして以後の通信がOKとなると言う訳です。JSSEの場合、SSL通信が発生すると、デフォルトの証明書(KeyStoreファイル)を見に行ってしまいます。KeyStoreファイルにサーバの証明書が無い場合、証明書の認証がNGとなって、通信が切断されます。ここで、JSSEのクラス(インタフェース)をラップして無条件に証明書を認証してしまえばOKとなります。メソッド的には isServerTrusted のあるクラスをラップすればOKだったと思います。※ここをいろいろ変更すれば自由にサーバの認証が出来ます。こんなもんでお役にたちましたでしょうか???では、また『いがぴょんの日記』を楽しみにしています。

ここからいがぴょん早速 怒濤のようなご教授いただき恐縮です。こ~ゆ~時日記やってて 本当に良かったと思います。また私の日記は投稿ページなので、みなさんの突っ込みこそがエンジンです。特に 今回のは仕事そのまんまでのハマりなので、すっごく助かります。,,,さしあたり JAVA WORLD 2000/04 を探さねば,,, (苦笑)2000/09/22 該当ページのコピーを入手。なるほど サンプルコードが載っていますですね。どうもありがとうございます。。。と書きつつこの作業は ヒトミ先輩が作業されますので、結果など顛末記は今しばらくお待ち下さい。

2000/09/26 httpsに単に接続するだけの動作確認は済みました。上手く行きました。情報をお寄せいただきありがとうございました。なお 私の利用環境はファイアウォール内なので、ファイアウォールの指定があります。(443では無くって 8080になってます)

import java.io.*;
import java.net.*;
import java.security.*;

public final class HttpsReader
{
        public static final void main(String[] args)
        {
                try{
                        Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
                        System.setProperty("java.protocol.handler.pkgs","com.sun.net.ssl.internal.www.protocol");
                        System.setProperty("https.proxyHost","<秘密なファイアウォールのIPアドレス>");
                        System.setProperty("https.proxyPort","8080");
                        URL urlRead=new URL("https://www.sun.com/");
                        BufferedReader reader=new BufferedReader(new InputStreamReader(urlRead.openStream()));
                        for(;;)
                        {
                                String readLine=reader.readLine();
                                if(readLine==null)break;
                                System.out.println(readLine);
                        }
                        reader.close();
                }catch(IOException ex){
                        System.out.println(ex.toString());
                        ex.printStackTrace();
                }
        }
}

コンパイルと実行は下記の如し。(Windows2000なので、クラスパスの区切り文字がセミコロンになってますです。) javac *.java pause SET CLASS_PATH=.;jcert.jar;jnet.jar;jsse.jar java -classpath %CLASS_PATH% HttpsReader

こんな感じで、外部のサーバには接続可能になりました。

それはいいやってことで、次は社内で自分で立てたサーバへのhttps接続です。今度はこいつでハマっています。

その 社内認証サーバへの接続サンプル(コンパイル・実行方法は HttpsReader.java と同様)

import java.io.*;
import java.net.*;
import java.security.*;
import javax.net.ssl.*;
import com.sun.net.ssl.*;

public final class HttpsReader2
{
        public static final void main(String[] args)
        {
                try{
                        Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
                        System.setProperty("java.protocol.handler.pkgs","com.sun.net.ssl.internal.www.protocol");

                        char[] passvalue="password".toCharArray();
                        SSLContext sslContext=SSLContext.getInstance("SSL");
                        KeyManagerFactory keymanagerFactory=KeyManagerFactory.getInstance("SunX509");
                        KeyStore keyStore=KeyStore.getInstance("JKS");
                        keyStore.load(new FileInputStream("O2-PC132155_NBB.crt"), passvalue);
                        keymanagerFactory.init(keyStore,passvalue);
                        sslContext.init(keymanagerFactory.getKeyManagers(),null,null);
                        SSLSocketFactory factory=sslContext.getSocketFactory();
                }catch(IOException ex){
                        System.out.println(ex.toString());
                        ex.printStackTrace();
                }catch(Exception ex){
                        System.out.println(ex.toString());
                        ex.printStackTrace();
                }
        }
}

発生する例外は下記の通り。

java.io.IOException: Invalid keystore format
        at sun.security.provider.JavaKeyStore.engineLoad(Unknown Source)
        at java.security.KeyStore.load(Unknown Source)
        at HttpsReader2.main(HttpsReader2.java:20)

サーバは WindowsNT4.0 Server + OptionPackって構成で、Webサーバは IIS4.0 + 認証サーバです (T_T)例外のメッセージをそのまま信じると、KeyStoreのフォーマットが妥当では無いということで、こいつがそのまま理由と思われます。こいつの証明書(公開鍵) をぶち込む設定などの段でやっぱし何かしらしくじっているのでしょう。JSSE 1.0.2 の KeyStore は デフォルトの "JKS"または指定して "PKCS12" が選択可能なのですが、OptionPack付属の認証サーバは DER(又はBase64) な X.509 か PKCS #7 かしか選択できず、それが原因かどうか不明ですが、うまく接続できません。(例はデフォルトのDERなX.509の証明書) 認証サーバ側で PKCS #12が選べそうに列挙されているものの『灰色』表示なんです (T_T)

はて、これの本番環境が 公的認証サーバに証明書を登録してもらえれば、さしあたりそのまんまイケるんですけれども、そうじゃあ無い設定での運用だったら、このままだったら動作させることができません。更に別の手だてにて調査依頼中...、、、それ以前に SSLに もう少し詳しくならなくては対応不能なような気もします。ってことで、継続中 (苦笑)

2000/09/27 社内の認証サーバへの接続問題ですが、一応解決できました。この場で報告いたします。そもそも IIS+認証サーバの証明書を JSSE 1.0.2の JKS に "そのまま" ぶち込もうとしていたのが間違っていました。これは一旦読み込んで書き出すことにより JSSE 1.0.2ネィティブな形式 (JKS形式) なファイルとして書き出すことができます。下記のコードが それの実現コードです。

import java.io.*;
import java.net.*;
import java.security.Security;
import java.security.KeyStore;
import javax.net.ssl.*;
import com.sun.net.ssl.*;

import java.util.*;

import java.security.cert.*;

public final class HttpsReader3
{
        public static final void main(String[] args)
        {
                try{
                        Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
                        System.setProperty("java.protocol.handler.pkgs","com.sun.net.ssl.internal.www.protocol");

                        final String FILE_NAME_CRT="O2-PC132155_NBB.crt";
                        FileInputStream inStream=new FileInputStream(FILE_NAME_CRT);
                        CertificateFactory cerFactory=CertificateFactory.getInstance("X.509");
                        Iterator iter=cerFactory.generateCertificates(inStream).iterator();
                        inStream.close();
                        KeyStore keyStore=KeyStore.getInstance("JKS");
                        char[] passvalue="passphrase".toCharArray();
                        keyStore.load(null,passvalue);

                        for(int index=1;iter.hasNext();index++)
                        {
                                Certificate cert=(Certificate)iter.next();
                                keyStore.setCertificateEntry(""+index,cert);
                                System.out.println("セット("+index+"):"+cert);
                        }

                        // 書き出し
                        {
                                OutputStream outStream=new BufferedOutputStream(new FileOutputStream(FILE_NAME_CRT+".keystore"));
                                keyStore.store(outStream,passvalue);
                                outStream.flush();
                                outStream.close();
                        }
                }catch(IOException ex){
                        System.out.println(ex.toString());
                        ex.printStackTrace();
                }catch(Exception ex){
                        System.out.println(ex.toString());
                        ex.printStackTrace();
                }
        }
}

手順的には IIS側(認証サーバ) の証明書を java.security.cert.CertificateFactoryを用いてJava側に取り込み (java.security.cert.CertificateFactory.generateCertificates() ) 生成された認証(リスト)を 新たに生成した KeyStore にぶち込んでファイル書き出ししたら、JKSが認識可能(読み込み可能)なものが作り出すという手順です。このファイルを そのまんま プログラミングで操作するのも1手法なのですが、手抜き的発想で、できあがったJKSな証明書を "C:\Program Files\JavaSoft\JRE\1.3\lib\security\jssecacerts"に名前変更したら、URLアクセスが 素で行きました。(ディレクトリ名や環境は適当に読み替えてください)このファイルが該当ディレクトリにあれば、そのまんま HttpsReaderサンプル は動作します。またこのファイルは HttpsReader2 サンプルでも読み込み可能です。(当然ですけどファイル名指定のファイル名は変更の必要があります :-)

これに関する情報は下記のページに載っていました。(そしてどのクラスをどのように使うかが やっとこさっとこ理解できたんです)ということで、詳細はそのページを見られよ。

いやはや、今回は疲れました。また どうにか動作するところまでこぎ着けることが出来たのは、ひとえに皆様のご助言のおかげです。みなさま、どうもありがとうございました m(_._)m レベルアップ: いがぴょんは 新たに 『SSL初級』 の呪文を覚えた

例えるなら、 『ヒャド』 レベルですね (苦笑)

Javaでコマンドシェルプログラミング

ご存じの方はご存じでしょうが、趣味でコマンドシェルプログラムをJava言語で作ってます。(さすがに ユーザは このページの読者の中では、ほんの数名と予想してますが,,,)ごく最近 マッチングの処理の殆どの箇所を、正規表現 (http://www.cacas.org/~wes/java/を利用) に書き換えてみました。(今までは ファイル名のマッチング処理のみ 正規表現で、あとはCollatorでの実装だった)あと ディレクトリのヒストリなんてものを実装してみました。いがぴょん的には 結構便利な感じになってきましたです。もうちょっと機能が追加されて ドキュメント整備が済んだら http://sourceforge.net にポストしようと企んでいます。(既に JavaCats や Vectorには登録済み、そういえば安藤さんの所には未ポスト) もちろん 最大の難関は 英語作文能力の不足です。致命的です。(それより前に LINUX対応も事前に済ませておくべきだろうか)趣味で自分の時間でポツポツ作っているから、なかなかに進捗が遅いです。さしあたり パイプライン処理とリダイレクション処理が欲しいのですが、ファイルコピー機能などの基本機能も先に欲しいです。(じゃないと ファイルコピーの際に わざわざ ネィティブのシェル環境に戻らなくてはいけないもので,,,)どなたか コマンドラインシェルに命かけてて、そしてヒマで実力派で なおかつ奇特な開発協力者が現れることを希望します (苦笑)

2000/09/20 さっそく共同開発への参加希望者の方からメール来ました。どうもどうも、ありがとうございます。力を合わせて頑張りましょう q(^o^)Pppp

2000/09/20 読者からの突っ込み

件名:Javaでコマンドシェルプログラミングいがぴょん様いつも日記を拝見させて頂いています。私も以前同じようなものを作りかけたのですが、作っているところを『地味だね』ということで一蹴されて、それ以来作っていません。JavaPressでも似たようなものを作っていた号がありましたが、非常に簡単なものにとどまっていました。さて、Linuxのカーネルの再構築のときには、シェルから直接Javaのクラスをwrapperで実行できるようにするオプションがあります。つまりshell$ chmod 700 execute.classshell$ ./execute.classなどとできるものです。今後は汎用的にバイナリをwrapperで実行できる機能がカーネルに加わり、javaは数あるバイナリの中のmiscという位置付けになるために、現在はobsoleteになっていますが、リダイレクトしたりとか、一応感覚的な使い方ができます。そもそもどこでも利用できる汎用的なシェルを作りたいと言うことですので、ネイティブなシェルにJavaを近づけるこれとは そもそも出発点が違いますが、新たに開発の協力者を発掘するという意味でも、改めてここでその意義を、両者を比較することにより明らかにしてもらえたら、javaユーザとしても読者としても嬉しいなあと、思います。期待してもいいでしょうか。なお、余談ですが、クロスプラットフォームなシェル環境としては、Mozilla上に構築されるXMLTerm

があります。XUL+Javascrptの実装であまり興味はないかと思いますが、一応MozillaとJavaの橋渡しを実装するBlackwoodProjectもありますので、よろしければ参考にしてください。BlackwoodProjectのWWWの和訳:

Ryuzi Kambe

ここからいがぴょんただいま返信を書き書き中,,,(と書きつつ 今日はこのまま放置かも (T_T)

2000/09/21 今日は激烈に忙しかったので、やっぱり更新できず。ただ このシェル開発用のMLは立ち上げました。そっちの方のウェブページ (つまり この一連の日記ページではありません) を 今晩反映しようと思います。


この日記について