web-dev-qa-db-ja.com

PKIXパスがWindows環境のトラストアンカーエラーとチェーンしない

私は、SSLとWebサービスがきめ細かいレベルでどのように機能するかについて、少しばかげています。いくつかのWebサービスを呼び出すシステムを開発しています。一部は安全なURLで、その他はほとんど問題ありません。ただし、現在、EndiciaのLabelServer Web APIとの統合を行っています。 Webサービスは、送料の計算と印刷に使用されます。

テストURLとWSDLは次の場所にあります https://www.envmgr.com/LabelService/EwsLabelService.asmx

Wsimportを使用してJavaこのWebサービスに接続するためのクライアントを作成およびセットアップしましたが、すべてを実行しようとするとエラーが発生します

PKIXパスの検証に失敗しました:Java.security.cert.CertPathValidatorException:パスがどのトラストアンカーともチェーンしていません

このエラーはここに文書化されています: Java7がトラストストアの証明書を信頼することを拒否しています

Java 7は、「不正な」鍵使用の自己署名証明書でエラーを強制します。この状況での不良は、keyCertSignが含まれていないと定義されています。WebサービスはJava 6.テストサーバーとしてのみ使用されているため、この証明書がこの証明書に適用される可能性があると確信できますが、それを確認する方法がわかりません。

解決されたバグレポートがあります( http://bugs.Java.com/bugdatabase/view_bug.do?bug_id=7018897 )が、これがどのように変換されるかはわかりませんWindows Tomcat環境の問題を修正します。証明書を自分のマシンにエクスポートしましたが、そこから続行する方法がわかりません。

編集:OpenSSLを使用して証明書を変更してキーストアに追加しようとしましたが、「トラストストアの証明書を信頼することを拒否する」リンクで説明されているように機能しませんでした。これは証明書の所有者が行うプロセスのようですよね?私のJava 7環境を構成して、この証明書を通過させることができる方法はあるのでしょうか。

8
IcedDante

デフォルトのJava証明書チェックはかなり厳格で、明らかに厳しくなっています。1つの回避策は、カスタムで SSLContext を初期化することです _X509TrustManager_ 。私がかつてテスト用に書いた、何もしない、つまり完全に安全ではないトラストマネージャは、次のようになります。

_TrustManager[] trustAllCerts = new TrustManager[]{
   new X509TrustManager() {
      public Java.security.cert.X509Certificate[] getAcceptedIssuers()
         {
            return null;
         }
      public void checkClientTrusted(
         Java.security.cert.X509Certificate[] certs,
         String authType )
         {
         }
      public void checkServerTrusted(
         Java.security.cert.X509Certificate[] certs,
         String authType )
         {
         }
   }
};
_

もちろん、実際のプログラムで実際に証明書チェーンをチェックする必要があります。次に、APIでSSLを構成する方法が他にない場合は、それを使用してSSLContextを初期化し、SSLContext.setDefault()を呼び出すことができます。 APIがデフォルトのSSLコンテキストを使用している場合、これは機能するはずです。

この場合、証明書チェーンは自己署名されていないため、キーの使用法は問題ではないようです。 URLをテストすると、リーフ証明書が自己署名されておらず、(2)チェーン内の他の2つの証明書で証明書署名が有効になっているように見えます。別の可能性としては、Java 6およびJava 7に個別のトラストストアがあり、ルート証明書がJava 7ストア。OpenSSLにアクセスできる場合は、サーバーから証明書チェーンを取得できます。

_openssl s_client -Host www.example.com -port 443 -showcerts
_

どうやらトラストストアを更新することが鍵でした(意地悪な意図)。 OPは次のよ​​うに報告します。

OpenSSL for Windows 64をダウンロードし、次のコマンドを使用して証明書チェーンをダウンロードしました。

_openssl s_client -Host www.webserviceurl.com -port 443 -showcerts > c:\temp\certchain_output.crt
_

次に、ブラウザのキーストアに次のようにインポートします(JDKのホームディレクトリ/ jre/lib/securityから)。

_keytool -import -alias ca -file certchain_output.crt -keystore cacerts -storepass changeit
_

X509TrustManagerを使用すると、効果的なソリューションも提供できると思います。

11
rhashimoto

証明書チェーン検証ロジックは、Java 6とJava 7.の間で実際に変更されました。有効期限の終了日が中間証明書がルート証明書の有効終了日より後になっているこれは a Java bug であり、JDK 1.7.0_72および1.8.0_25で修正されました。

JDKをアップグレードできない場合は、デバッグ環境にあり、キーストアを制御できるというので、これが回避策です。もちろん、どの証明書も変更できません(秘密鍵がないため)。ただし、中間証明書またはサーバー証明書をローカルキーストアにインポートできます。つまり、デフォルトで信頼され、残りはチェーンの検証は問題なく行われます。

  1. www.envmgr.comまたはwww.starfieldtech.comの証明書をtrusted_certificate.pemとしてダウンロードします
  2. keytoolを使用して、keytool -keystore my_keystore -importcert -file trusted_certificate.pemmy_keystoreという名前のローカルキーストアに証明書をインポートします
  3. wsimport -J-Djavax.net.ssl.trustStore=my_keystore https://www.envmgr.com/LabelService/EwsLabelService.asmxを起動します
7
rxg

Keytoolを使用して、必要な証明書をJavaトラストストアをjdk_xxx/jre/lib/security/cacertsにインポートしてみてください。

詳細なデバッグ情報を表示するには、jvmパラメータDjavax.net.debug = sslを設定します

2
Simone

ラシモトは私に役立つ解決策を見つけるのに役立ちました:

OpenSSL for Windows 64をダウンロードし、次のコマンドを使用して証明書チェーンをダウンロードしました。

openssl s_client -Host www.webserviceurl.com -port 443 -showcerts > c:\temp\certchain_output.crt

次に、ブラウザのキーストアに次のようにインポートします(JDKのホームディレクトリ/ jre/lib/securityから)。

keytool -import -alias ca -file certchain_output.crt -keystore cacerts -storepass changeit

X509TrustManagerを使用すると、効果的なソリューションも提供できると思います。

1
IcedDante

これを試してみてください、それはすべてを受け入れます

TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public Java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; }
            public void checkClientTrusted(X509Certificate[] certs, String authType) { }
            public void checkServerTrusted(X509Certificate[] certs, String authType) { }

        } };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new Java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        // Create all-trusting Host name verifier
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) { return true; }
        };
        // Install the all-trusting Host verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
0
Rupesh Kumar