javax.net.ssl.SSLException: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty [duplicate]
Asked Answered
G

4

13

I'm looking to parse an XML file that updates said file daily - the only issue I've run into is that they use their own certificate (https://...) and I can't use that specific URL, nor is there an http://... link available.

URL url = new URL("https://...");
...
Document document = db.parse(url.openStream());

This code throws the following exception while running my tests:

javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty

I've seen a variety of suggestions dealing with creating various classes to deal with this kind of connection or with a personal server, as well as adding the certificate to a keystore and then adding that keystore to the Java project, but I've been unable to do that and am looking for a slightly simpler way for me to go about accessing the XML online.

Grin answered 4/12, 2011 at 20:7 Comment(3)
It looks like you've changed your truststore settings not to use the default ones. What have you changed?Towhee
This had the effect of removing the default trust store, hence you got an empty trustAnchors parameter. There always must be a non-empty truststore.Towhee
See this How to Answer[1] In short, the keystore can't be found. [1]: https://mcmap.net/q/64150/-error-trustanchors-parameter-must-be-non-emptyThurifer
K
12

You need a truststore to store SSL certificates. You can download the certificate using your preferred web browser. To load the certificate into the truststore, you need the "keytool" program, which comes with the JDK.

For example, if your certificate file is named "certificate.crt" and you want to create a truststore named "secure.ts", you can invoke keytool as follows:

keytool -importcert -keystore secure.ts -storepass S3cuR3pas$! -file certificate.crt

Now, you must tell your program where the keystore is and the password to open it, defining the system properties "javax.net.ssl.trustStore" and "javax.net.ssl.trustStorePassword" before opening the connection

URL url = new URL("https://...");

System.setProperty("javax.net.ssl.trustStore", "secure.ts");
System.setProperty("javax.net.ssl.trustStorePassword", "S3cuR3pas$!");
...
Document document = db.parse(url.openStream());
Kassandrakassaraba answered 17/9, 2013 at 10:1 Comment(0)
P
3

This curious message means the truststore wasn't found.

Nothing whatsoever to do with XML BTW.

Pheon answered 4/12, 2011 at 21:36 Comment(10)
@Grin See the Javadoc: Security/JSSE Reference Guide.Pheon
I had renamed <java-home>/lib/security/cacerts to <java-home>/lib/security/cacerts_orig previously in an attempt to add the certificate I have to a keystore - I've fixed that and now get the following error: 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 targetGrin
@Grin so your truststore doesn't trust the server's certificate. So it is probably self-signed. You need to import it into your cacerts, or more probably copy your cacerts to a local truststore, import the server certificate into that, and use that as the truststore. See forums.oracle.com/forums/… for a possible import solution. Best solution of all is to get the server to use a certificate signed by a CA.Pheon
I have the certificate from the site in the lib/security/ folder - I have looked at InstallCert.java but had some issues using that when compiling it and am having error pre-compile with InstallCertJFrame.java as well. The certificate I deal with is from the university I go to and they are (to the extent of my knowledge) signed by a CA.Grin
I've also seen suggestions of disabling certification validation entirely, which I'm fine with as well, although I'd rather not just nab all of the example code if it isn't necessary to disable the validation process.Grin
@Grin (a) What issues? It compiles and executes fine for me. (b) I've never understood the enthusiasm for disabling certificate verification. If you don't want it secure, why use SSL at all? (c) putting certificates into lib/security doesn't accomplish anything.Pheon
a) various formatting issues that Eclipse doesn't like, b) because this is a university run website that we are parsing data from to use for an Android application - I don't have a preference as to whether or not it's SSL, just as long as I can parse data from the link instead of having to save it as a local file for a demo.Grin
Also tried InstallCertJFrame again and got it working - only issue is it throws an error (Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: || or UnknownHostException without the https:// preceeding the link) when attempting to import from the site (https://.../file.xml) I'm accessing.Grin
@Acetaminophen, so far, your problem had nothing to do with XML (@EJP correctly re-tagged your question). Now, UnknownHostException: I'm not sure why you would remove the https:// preceding the link. NumberFormatException: this may have to do with the processing of your XML document at some stage. This should probably be addressed in a different question, since it has nothing to do with SSL now.Towhee
@Grin You cannot convince me that 'Eclipse formatting issues' prevented you from executing this code.Pheon
T
2

You can try with this:

String javaHomePath = System.getProperty("java.home");
String keystore = javaHomePath + "/lib/security/cacerts";
String storepass= "changeit";
String storetype= "JKS";

String[][] props = {
    { "javax.net.ssl.trustStore", keystore, },
    { "javax.net.ssl.keyStore", keystore, },
    { "javax.net.ssl.keyStorePassword", storepass, },
    { "javax.net.ssl.keyStoreType", storetype, },
};
for (int i = 0; i < props.length; i++) {
    System.getProperties().setProperty(props[i][0], props[i][1]);
}
// Now you can proceed to connect to call the webservice.
// SSL will be used automatically if the service endpoint url 
// starts with <a href="https://." target="_blank"         rel="nofollow">https://.</a>
// The server will send its certificate signed by verisign and 
// client will trust and authenticate the server as it recognizes 
// verisign as one trusted root.
Trimetallic answered 30/12, 2015 at 19:16 Comment(0)
K
-3

I ran into the same Exception for my MAC OSX (Yosemite), while developing Java 6 applications. You need to download and install Apple's Java for OSX 2014:

http://support.apple.com/kb/DL1572

Kinata answered 4/1, 2015 at 23:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.