Unable to find valid certification path to request target solution

Keywords: Apache JDK

Today, after the sale, the consulting customer bought the certificate. There was a 400 error in https request. Let me help you get it. Seeing that the customer's code seems to be no problem, I tried it myself, and there really is an exception. Record to avoid being pitted later.

Scenario: Two-way validation of SL, requests need to bring client certificates.

Maybe you will encounter different problems, but the problem is a customer feedback. apache's httpclient is used. The registration certificate requests the server and then reports 400 errors. The error message is unable to find valid certification path to request target.

The customer code is probably like this:

static public void client() throws Exception {
		// Trust own CA and all self-signed certs
		File cert = new File("D:/test/cert.pfx");
		KeyStore keyStore = KeyStore.getInstance("pkcs12");
		keyStore.load(new FileInputStream(cert), "cert_password".toCharArray());
		SSLContext sslcontext = SSLContexts.custom()
				.loadKeyMaterial(keyStore, "cert_password".toCharArray()).build();
		// Allow TLSv1 protocol only
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
				SSLConnectionSocketFactory.getDefaultHostnameVerifier());
		CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
		HttpGet httpget = new HttpGet("https://domains.com/");
		System.out.println("Executing request " + httpget.getRequestLine());
		HttpResponse response = httpclient.execute(httpget);
		HttpEntity entity = response.getEntity();
		System.out.println("----------------------------------------");
		System.out.println(response.getStatusLine());
		EntityUtils.consume(entity);
	}

Actually, the configuration given by httpclient is similar, but this is the reason why the server can not be trusted locally. That means adding a list of certificates on the trusted server locally. Strangely, both the operating system and the jdk have a trust list, and the certificates of the customer's formal environment are certainly trusted. Why does this happen again? Later, the certificate was analyzed, and one reason for suspicion was that the certificate level exceeded three levels (temporarily unable to verify, only one certificate).

The solution is:

SSLContext sslcontext = SSLContexts.custom()
				.loadKeyMaterial(keyStore, "cert_password".toCharArray())
				.loadTrustMaterial(new File("trust_ca.jks"),"trust_password".toCharArray(), new TrustSelfSignedStrategy()).build();

A trustmaterial is added, which manually synthesizes a trust list and brings in the request.

jks = key file + certificate of issuing agency, which can be synthesized online on some ca agency's official website.

There may be different reasons for everyone's mistakes. This is just one of them.

Posted by joel426 on Sun, 03 Feb 2019 13:51:15 -0800