6

Web アプリケーションで使用したキーストア ファイルが先週期限切れになりました。ずっと前に生成しました。そこで、keytool を使用して新しい証明書の生成を開始しました。この証明書を使用して、トランザクション サーバーと Web サーバーを接続しました。このアプリケーションに自己署名証明書を使用したかったのです。次のコマンドを使用して生成し、トランザクション サーバーの自己署名キーを生成します。

keytool -genkey -keystore keys/SvrKeyStore -keyalg rsa -validity 365 -alias Svr -storepass 123456 -keypass abcdefg -dname "CN=One1, OU=Development1, O=One, L=Bamba, S=Western Prov1, C=S1"

Web アプリケーションのキーストアを生成する次のコマンド

keytool -genkey -keystore keys/ClientKeyStore -keyalg rsa -validity 365 -alias Web -storepass 123456 -keypass abcdefg -dname "CN=One, OU=Development, O=One, L=Bamba, S=Western Prov, C=SL"

トランザクションサーバーで次のコードを使用して、ソケット接続を作成しました

          String KEYSTORE = Config.KEYSTORE_FILE;//SvrKeyStore  keystore file
          char[] KEYSTOREPW = "123456".toCharArray();
          char[] KEYPW = "abcdefg".toCharArray();
          com.sun.net.ssl.TrustManagerFactory tmf;

          boolean requireClientAuthentication;

          java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl.
                                             Provider());
          java.security.KeyStore keystore = java.security.KeyStore.getInstance(
              "JKS");
          keystore.load(new FileInputStream(KEYSTORE), KEYSTOREPW);

          com.sun.net.ssl.KeyManagerFactory kmf = com.sun.net.ssl.
              KeyManagerFactory.getInstance("SunX509");
          kmf.init(keystore, KEYPW);

          com.sun.net.ssl.SSLContext sslc = com.sun.net.ssl.SSLContext.
              getInstance("SSLv3");
          tmf = com.sun.net.ssl.TrustManagerFactory.getInstance("sunx509");
          tmf.init(keystore);

          sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
          SSLServerSocketFactory ssf = sslc.getServerSocketFactory();
          SSLServerSocket ssocket = (SSLServerSocket) ssf.createServerSocket(port);
          ssocket.setNeedClientAuth(true);

しかし、アプリケーションで使用し、Web サーバーを介してトランザクション サーバーに接続しようとすると、次の例外が発生します。

javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHands
hakeException: java.security.cert.CertificateException: Untrusted Server Certifi
cate Chain
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.jav
a:1172)
        at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:
65)
        at net.schubart.fixme.internal.MessageInput.readExactly(MessageInput.jav
a:166)
        at net.schubart.fixme.internal.MessageInput.readMessage(MessageInput.jav
a:78)
        at cc.aot.itsWeb.ClientWriterThread.run(ClientWriterThread.java:241)
        at java.lang.Thread.run(Thread.java:619)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateEx
ception: Untrusted Server Certificate Chain
        at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1
520)
        at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:182)
        at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:176)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Clien
tHandshaker.java:975)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHa
ndshaker.java:123)
        at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:5
11)
        at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.jav
a:449)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.j
ava:817)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SS
LSocketImpl.java:1029)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.
java:621)
        at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.ja
va:59)
        at java.io.OutputStream.write(OutputStream.java:58)

どこに問題があるのか​​誰か教えてください

4

3 に答える 3

11

まず、com.sun.net.sslパッケージとクラスを直接使用しないでください。JSSEのアーキテクチャは、ファクトリを使用して後でプロバイダーを指定できるように構築されています。代わりに(と同じ)をjavax.net.ssl.TrustManagerFactory使用してください。(トラストマネージャーアルゴリズムの代わりに使用することをお勧めします。これは通常、Sunプロバイダーのデフォルトであるため、またはより適切に使用します)。KeyManagerFactorySSLContext"PKIX""SunX509"TrustManagerFactory.getDefaultAlgorithm()

次に、クライアント証明書認証を使用している場合を除き、クライアント側でキーマネージャーを設定する必要はありません。

最後に(そしておそらく最も重要なことですが)、サーバー側で生成した自己署名証明書(秘密鍵ではなく証明書のみ)をエクスポートし、信頼ストアとして使用するキーストアにインポートする必要があります。クライアント側。

証明書を生成するときは、必ずを使用する必要がありますCN=the.server.host.name

keytool -genkey -keystore server-keystore.jks -alias server_alias \
        -dname "CN=the.server.host.name,OU=whateveryoulike" \
        -keyalg "RSA" -sigalg "SHA1withRSA" -keysize 2048 -validity 365

keytool -export -keystore server-keystore.jks -alias server_alias -file server.crt

keytool -import -keystore client-truststore.jks -file server.crt

クライアント証明書認証を使用する場合は、server-keystoreとclient-truststoreをそれぞれclient-keystoreとserver-truststoreに置き換えて、操作を繰り返す必要があります。

この場合、同じファイルserver-keystore.jksserver-truststore.jksある可能性がありますが、その必要はありません(クライアント側でも同じです)。

于 2010-09-26T12:25:35.407 に答える
0

あなたがする必要があったのは、keytool -selfcert - alias XXX -validity DDD でした。ここで、XXX は以前と同じエイリアスで、DDD はサーバー証明書の有効期限が切れるまでの日数です。次に、その証明書をエクスポートし、クライアントのトラストストアにインポートします。クライアントに対して逆の手順を繰り返します。エクスポート/インポートの部分を省略しました。

ただし、そのコードの多くは現在廃止されています。addProvider() を呼び出す必要はなく、com.sun.net.ssl を残りの部分で javax.net.ssl に変更できます。

于 2010-09-26T12:19:46.433 に答える
0

これを理解するには、証明書がどのように機能するかを理解する必要があります。

誰でも証明書を作成できるため (あなたが行ったように)、証明書を作成するだけでは十分ではありません。証明書は信頼できるものでなければなりません。証明書は、信頼されている別の証明書によって署名されている場合にのみ信頼されます。信頼の「フード チェーン」の頂点には、いくつかの主要な CA があり、証明書を「公的に信頼できる」ものにするためにお金を払うことができます (コンピュータには証明書がインストールされています)。

もちろん、アプリケーションを注文するために CA に支払う必要はありませんが、この動作を模倣する必要があります。おそらくあなたがしなければならないことは、サーバー/クライアントの公開鍵をエクスポートし、ある種の信頼できるストアにインストールすることです.

API を使用して、信頼できる証明書の場所を定義する方法を確認してください。

于 2010-09-26T12:20:10.857 に答える