简体   繁体   中英

Use certificate for HTTPS request in Java

I want to call some web services through an HTTPS connection in Java. The certificate authority gave me a PKCS12 file but I get a

sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

due to

javax.net.ssl.SSLHandshakeException

Here is the code I am executing :

System.setProperty("javax.net.ssl.keyStoreType", "JKS");
System.setProperty("javax.net.ssl.keyStore", "path/toto2.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "pwd");
System.setProperty("javax.net.ssl.trustStoreType", "JKS");
System.setProperty("javax.net.ssl.trustStore", "path/toto2.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "pwd");
System.setProperty("proxySet","true") ;
System.setProperty("https.proxyHost", "XXX") ;
System.setProperty("https.proxyPort", "XXX") ;

I first tried to give the PKCS12 file, then the JKS but I had the same error.

I tried another solution, with curl. So I extracted certificates from the PKCS12 and the requests successed.

Here are the commands that I used to extract the different files from the P12 :

openssl pkcs12 -in file.p12 -nocerts -nodes -out clientcert.key
openssl pkcs12 -in file.p12 -clcerts -nokeys -out clientcert.cer
openssl pkcs12 -in file.p12 -cacerts -nokeys -chain -out cacerts.cer

Am I wrong with the way I use those files in Java ?

PKCS12 normally contains a privatekey and cert (chain) combination, and is used to authenticate your system ie the client, which is done with the javax.net.ssl.keyStore* properties. You should specify type PKCS12, although some Java8 versions (only!) can read PKCS12 when you specify JKS.

It typically does NOT authenticate the server(s), which is what javax.net.ssl.trustStore* is for, so don't use it there. Depending on the server(s?), you may or may not need a custom truststore different from the P12 and also different from Java's default. Look at the cert chain used by the server with a browser or other tool like curl or keytool -printcert -sslserver host[:port] and determine whether it uses a public root CA like Verisign-now-Symantec-now-Digicert or GoDaddy, which will already be in Java's default truststore, or a 'private' CA or even a self-signed cert, in which case you should either add that cert to the default truststore or if you can't or don't want to modify your JVM put that cert in a keystore file you use as the truststore.

PS: the ValidatorException causes the SSLHandshakeException not the reverse.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM