How to set up Java VM to use the root certificates (truststore) handled by Mac OS X
Asked Answered
F

6

33

I get the following exception while using the scribe OAuth library.

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

Based on some googling it seems I should set up the JVM truststore somehow.

Why do I need to do this? How can I instruct the Java VM to use the default truststore of the os? (Mac OS X in my case).

Fitts answered 11/1, 2013 at 14:50 Comment(0)
F
19

I can setup the default truststore by adding this system propery when launching the VM:

-Djavax.net.ssl.trustStore=/Library/Java/Home/lib/security/cacerts

I still don't understand why do I need to do this. This should be the default. It's also very annoying to add this every time. Is there a better way, e.g. some OS settings?

Fitts answered 11/1, 2013 at 17:19 Comment(3)
Re: "This should be the default." Java is often updated out-of-sync from the host operating system. Using a separate truststore allows known-insecure certificates to be untrusted more quickly for security, and allows Java apps running on older operating systems that might not themselves bundle all the modern root CAs — and embedded systems that might not have any system CA truststore — to be kept secure. Similar reasoning is why many browsers bypass the system truststore. In fact, Chrome is moving towards this model and away from the system truststore.Politic
@Politic There’s actually a defined mechanism to check for revoked certificates that should be used rather than let every application bring its own trust store. Installing a company root certificate is already a nightmare with so many trust stores scattered over each client system.Denbrook
@Denbrook I don't disagree! However, checking revocation in one place is the same problem as checking trust in one place: the desktop ecosystem is just too fragmented and too many big players have financial stake in that fragmentation, for it to be a realistic norm.Politic
T
31

You can use the Apple JCA Provider to use the OSX keychain as the java trust store. Just start the JVM with the following system property:

-Djavax.net.ssl.trustStoreType=KeychainStore

You can set this property for every started JVM using the JAVA_TOOL_OPTIONS environment variable, as described in hagrawal's answer.

Tiercel answered 20/7, 2019 at 0:57 Comment(7)
This worked to have Fiddler working for me. Thank you!Madea
This by far is the best answer. Thank you!Mashe
FYI, Apple JCA Provider@Java 11Broach
This appears to break requests that use certs from the default truststore file, sadly. Apparently it won't obey both at the same time.Sustainer
What if your spring application is running in a docker container? I suspect KeychainStore will not be accessible there. Any idea how to fix it in that case?Postboy
@Sustainer You're right. This seems to be a new bug, because it used to work. Unfortunately, I was unable to find out if it's a problem of Java or the Apple JCE provider or macOS itself. :-(Denbrook
This worked after many days of struggling. Thank you!Fluviatile
F
19

I can setup the default truststore by adding this system propery when launching the VM:

-Djavax.net.ssl.trustStore=/Library/Java/Home/lib/security/cacerts

I still don't understand why do I need to do this. This should be the default. It's also very annoying to add this every time. Is there a better way, e.g. some OS settings?

Fitts answered 11/1, 2013 at 17:19 Comment(3)
Re: "This should be the default." Java is often updated out-of-sync from the host operating system. Using a separate truststore allows known-insecure certificates to be untrusted more quickly for security, and allows Java apps running on older operating systems that might not themselves bundle all the modern root CAs — and embedded systems that might not have any system CA truststore — to be kept secure. Similar reasoning is why many browsers bypass the system truststore. In fact, Chrome is moving towards this model and away from the system truststore.Politic
@Politic There’s actually a defined mechanism to check for revoked certificates that should be used rather than let every application bring its own trust store. Installing a company root certificate is already a nightmare with so many trust stores scattered over each client system.Denbrook
@Denbrook I don't disagree! However, checking revocation in one place is the same problem as checking trust in one place: the desktop ecosystem is just too fragmented and too many big players have financial stake in that fragmentation, for it to be a realistic norm.Politic
W
10

I think it is clear to everyone that JAVA needs a way to identify the default truststore, when dealing with SSL, so this information has be passed to JAVA in some way, so I think the "updated" question in hand is how to do it in a do-it-one-time-and-then-forget-everytime way.

The best way I could found was by setting JAVA_TOOL_OPTIONS environment variable at your OS level, if this environment variable is set then JAVA will be launched by default with the arguments you have provided in this environment variable.

So, you need not to set -Djavax.net.ssl.trustStore=/Library/Java/Home/lib/security/cacerts each time JVM is launched, instead set JAVA_TOOL_OPTIONS environment variable "once" at your OS level with value as -Djavax.net.ssl.trustStore=/Library/Java/Home/lib/security/cacerts and then you are done.

Below is the excerpt from #1 of "Further readings":

When this environment variable is set, the JNI_CreateJavaVM function (in the JNI Invocation API) prepends the value of the environment variable to the options supplied in its JavaVMInitArgs argument.

Only caveat to watch out is mentioned below, excerpt from #1 of "Further readings":

In some cases this option is disabled for security reasons, for example, on Solaris OS the option is disabled when the effective user or group ID differs from the real ID.

Below is one more caveat (excerpt from #1 of "Further readings") to watch out but I think since context is not about VM selection argument so it is not relevant, but just to mention.

Since this environment variable is examined at the time that JNI_CreateJavaVM is called, it cannot be used to augment the command line with options that would normally be handled by the launcher, for example, VM selection using the -client or the -server option.

Further readings:

Wonderstricken answered 29/12, 2016 at 1:14 Comment(0)
O
3

I tried to to this right now, but I had issues and in the end that didn't work for me. But I played around and found out that the following solution worked for me. It's setting the following to the jvm:

-Djavax.net.ssl.trustStoreType=KeychainStore -Djavax.net.ssl.trustStore=/Library/Keychains/System.keychain

e.g. via

export JAVA_TOOL_OPTIONS="-Djavax.net.ssl.trustStoreType=KeychainStore -Djavax.net.ssl.trustStore=/Library/Keychains/System.keychain"
Octamerous answered 11/10, 2023 at 9:21 Comment(1)
What version of java does this work on? Stepping through the OpenJDK 21 code, javax.net.ssl.trustStore is ignored.Corsica
D
1

To make Java use the macOS keychain, pass the following parameter to the Java VM:

-Djavax.net.ssl.trustStoreType=KeychainStore 

However, there seems to be a bug in either the Apple JCE provider (that handles the keychain access) or perhaps in macOS itself, which obviously leads to the issue that certificates in the login and system keychain are seen by Java, but not those in system roots. Unfortunately, the latter is exactly where all the system provided certificates are stored. :-(

Some users report that adding

-Djavax.net.ssl.trustStore=NUL

or

-Djavax.net.ssl.trustStore=/dev/null

has resolved the issue for them. I cannot confirm that. It did not work for me when I tried it.

I'm pretty sure that this used to work properly, though.

Denbrook answered 3/10, 2022 at 14:11 Comment(0)
V
0

Ah! i know this problem. I had similar issue, and it was related to the Java bindings in OSX. Once i installed the latest version, it got fixed.

https://support.apple.com/en-us/HT204036

Vela answered 28/12, 2016 at 15:46 Comment(1)
Alas, link is dead.Corsica

© 2022 - 2024 — McMap. All rights reserved.