1. ホーム
  2. ssl

[解決済み] Windows環境でPKIXパスがどのトラストアンカーとも連鎖しないエラーが発生する。

2022-01-29 20:38:37

質問内容

SSLとWebservicesがどのように細かいレベルで動作するのか、少し馬鹿にしています。私はいくつかのWebサービスを呼び出すシステムを開発していますが、その中にはセキュリティで保護されたURLのものとそうでないものがあり、ほとんど問題なく利用できています。しかし現在、私はEndiciaのLabelServer Web APIとの統合を行なっている。このウェブサービスは、郵便料金の計算と印刷に使用されます。

テストURLとWSDLは、以下の通りです。 https://www.envmgr.com/LabelService/EwsLabelService.asmx

このウェブサービスに接続するためのJavaクライアントをwsimportで作成し、セットアップしましたが、それをすべて実行しようとすると、エラーが発生します。

PKIXパスの検証に失敗しました:java.security.cert.CertPathValidatorException。パスはどのトラストアンカーにも連結されていません。

このエラーはこちらに記載されています。 Java7 トラストストアの証明書を信頼することを拒否している

の中で、Java 7 がどのように "bad" の鍵使用で自己署名証明書を強制的にエラーにするかについて述べられています。この状況での悪いとは、keyCertSignを含んでいないことと定義されています。このウェブサービスは、Java 6で動作します。私は、この証明書がテストサーバーとしてのみ使用されているため、この状況が適用されるかもしれないと信じることができますが、それを検証する方法がわかりません。

解決済みのバグレポートがあるんですが( http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7018897 )ですが、WindowsのTomcat環境での問題解決につながるものがあるのか、よくわかりません。証明書を自分のマシンにエクスポートしましたが、そこからどのように進めばよいのかがわかりません。

EDIT リンク先の "Refusing to trust certificate in trust store" にあるように、OpenSSL を使って証明書を修正し、鍵ストアに追加してみましたが、うまくいきませんでした。これは、証明書の所有者が行う処理のようですね?この証明書を通すようにJava 7の環境を設定する方法はないでしょうかね。

解決方法は?

Java のデフォルトの証明書チェックはかなり厳しく、さらに厳しくなっているようです。回避策のひとつは 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 )
         {
         }
   }
};

もちろん、実際のプログラムで証明書チェーンを実際に確認したいと思うでしょう。そこで SSLContext を呼び出し、それを使って SSLContext.setDefault() もしあなたのAPIにSSLを設定する他の方法がない場合。もし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を使用することも有効な解決策になると思います。