Java x64& InstallCert.java& jssecacerts:无法找到请求目标的有效证书路径

时间:2018-01-09 14:57:28

标签: java windows security certificate keystore

我有一个基于java的自定义工具来ping指定端口上的服务器。该工具在Windows 7 x86上运行正常,但在使用Java x64的Windows 7 x64上出现以下错误时失败:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

以下是一些细节:

首先,为了ping这个服务器,我保存了它的CA证书。为此,我使用了以下工具: https://github.com/escline/InstallCert/blob/master/InstallCert.java

此工具的结果是jssecacerts文件。我将此文件放在C:\ Program Files \ Java \ jre1.8.0_77 \ lib \ security中 定义了JAVA_HOME变量:C:\ Program Files \ Java \ jre1.8.0_77

然后,我使用我的工具ping服务器:

package CallNotificationService;

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

import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import java.security.SecureRandom;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

public class CallNotificationService {


    public static void main(String[] args) throws Exception 
    { 

        String MyServ = args[0];
        String certificate = args[1];
        String certPassword = args[2];

        System.out.println(MyServ + " " + certificate + " " + certPassword);

        String notificationService = "https://" + MyServ + ":9443/available";

        URL url = new URL(notificationService);

        HostnameVerifier HostValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };      

        HttpsURLConnection.setDefaultHostnameVerifier(HostValid);

        HttpsURLConnection con = (HttpsURLConnection) url.openConnection();

        con.setSSLSocketFactory(getFactory(new File(certificate), certPassword));


        BufferedReader intpam = new BufferedReader(
        new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = intpam.readLine()) != null) {
            response.append(inputLine);
        }
        intpam.close();

        System.out.println(response.toString());

    }

    public static SSLSocketFactory getFactory( File pKeyFile, String pKeyPassword ) throws Exception {


          KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
          KeyStore keyStore = KeyStore.getInstance("PKCS12");

          InputStream keyInput = new FileInputStream(pKeyFile);
          keyStore.load(keyInput, pKeyPassword.toCharArray());
          keyInput.close();

          keyManagerFactory.init(keyStore, pKeyPassword.toCharArray());

          SSLContext context = SSLContext.getInstance("TLS");
          context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
          return context.getSocketFactory();

    }

}

在stderr中,我有以下内容:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.ssl.Alerts.getSSLException(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
    at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
    at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
    at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
    at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
    at sun.security.ssl.Handshaker.processLoop(Unknown Source)
    at sun.security.ssl.Handshaker.process_record(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
    at CallNotificationService.CallNotificationService.main(CallNotificationService.java:48)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
    at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
    at sun.security.validator.Validator.validate(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
    ... 14 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.build(Unknown Source)
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
    at java.security.cert.CertPathBuilder.build(Unknown Source)
    ... 20 more

我还尝试按照文档(https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/properties.html)将jssecacerts放到%USER_HOME \ security \ trusted.jssecacerts,但它没有帮助。

注意:如果我在命令行中指定-Djavax.net.ssl.trustStore = jssecacerts,则 DOES 有效(在这种情况下,jssecacerts放置在与我的jar应用程序相同的文件夹。)

问题:,因为此代码在x86中有效,我想x64中的这个失败可能与jssecacerts位置或类似的东西有关。 我应该尝试解决此问题? x64中是否有特定的jssecacerts位置?

谢谢, 浣熊

0 个答案:

没有答案