193

How does my Java program know where my keystore containing the certificate is?

Or alternatively: How do I tell my Java program where to look for the keystore?

After specifying the keystore in some way, how to specify the certificate to use for authenticating the server to client?

Lii
  • 11,553
  • 8
  • 64
  • 88
deborah
  • 1,945
  • 2
  • 12
  • 6
  • better is avoid of usage the System.setProperty setting (the approaches below), see: https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#ex1 , how to construct the KeyManagerFactory for SSLContext – Marek-A- Jul 17 '19 at 11:23

6 Answers6

341

SSL properties are set at the JVM level via system properties. Meaning you can either set them when you run the program (java -D....) Or you can set them in code by doing System.setProperty.

The specific keys you have to set are below:

javax.net.ssl.keyStore- Location of the Java keystore file containing an application process's own certificate and private key. On Windows, the specified pathname must use forward slashes, /, in place of backslashes.

javax.net.ssl.keyStorePassword - Password to access the private key from the keystore file specified by javax.net.ssl.keyStore. This password is used twice: To unlock the keystore file (store password), and To decrypt the private key stored in the keystore (key password).

javax.net.ssl.trustStore - Location of the Java keystore file containing the collection of CA certificates trusted by this application process (trust store). On Windows, the specified pathname must use forward slashes, /, in place of backslashes, \.

If a trust store location is not specified using this property, the SunJSSE implementation searches for and uses a keystore file in the following locations (in order):

  1. $JAVA_HOME/lib/security/jssecacerts
  2. $JAVA_HOME/lib/security/cacerts

javax.net.ssl.trustStorePassword - Password to unlock the keystore file (store password) specified by javax.net.ssl.trustStore.

javax.net.ssl.trustStoreType - (Optional) For Java keystore file format, this property has the value jks (or JKS). You do not normally specify this property, because its default value is already jks.

javax.net.debug - To switch on logging for the SSL/TLS layer, set this property to ssl.

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
Karthik Ramachandran
  • 11,925
  • 10
  • 45
  • 53
  • 22
    It would be more appropriate to link to the document from which this is quoted. I guess this is it: http://fusesource.com/docs/broker/5.3/security/SSL-SysProps.html – Bruno Jul 20 '11 at 21:41
  • 5
    The official document should be JSSE Reference Guide: http://docs.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#Customization – aleung Apr 19 '13 at 09:19
  • 5
    JDK7 http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#Customization is more appropriate now. – Rick-777 Oct 12 '13 at 14:03
  • 12
    For anyone who may want to edit the system trust store, the default password is "changeit": https://community.oracle.com/thread/1540678?start=0&tstart=0 – cwc May 27 '14 at 02:58
  • 1
    +1 for the javax.net.ssl.trustStorePassword prop. I'd been looking around for a while and this was the first that mentioned it. – jgreen Mar 05 '19 at 23:57
  • 1
    JDK 8: https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html – Alexey Ivanov Sep 15 '21 at 18:18
  • `On Windows, the specified pathname must use forward slashes, /, in place of backslashes, \.` This doesn't seem to be necessary - could someone elaborate? – ryanwebjackson Feb 13 '23 at 15:53
125
System.setProperty("javax.net.ssl.trustStore", path_to_your_jks_file);
LINGS
  • 3,560
  • 5
  • 34
  • 47
DaveH
  • 7,187
  • 5
  • 32
  • 53
  • 4
    anyone knows how to reference this on a windows box? System.setProperty("javax.net.ssl.trustStore", "C:\\Program Files (x86)\\Java\\jdk1.7.0_21\\jre\\lib\\security\\cacerts"); isn't working for me :( – simgineer Jul 17 '13 at 22:39
  • 6
    On Windows, the specified pathname must use forward slashes, /, in place of backslashes, \. – Droidman Mar 04 '15 at 19:35
  • 1
    Did this work? I used same code where my 'jks' file contains a CA Certificate. But I still get **javax.xml.ws.WebServiceException: org.apache.axis2.AxisFault: Transport error: 403 Error: Forbidden** error when I call the client code through the SOAP generated stubs. Any ideas? – james2611nov Mar 10 '15 at 21:25
  • 2
    There is also a password system property (javax.net.ssl.trustStorePassword). Could also be passed as JVM arguments -Djavax.net.ssl.trustStore=clientTrustStore.key -Djavax.net.ssl.trustStorePassword=customPassword Refer https://docs.oracle.com/javadb/10.8.3.0/adminguide/cadminsslclient.html – Kingsly Feb 27 '19 at 21:42
  • 2
    @james2611nov: If you're getting an HTTP 403 error (or any other HTTP response) calling an HTTPS endpoint, then that means that you successfully got past the TLS setup: the HTTP interactions take place only once the TLS channel is set up (else they couldn't be protected). So -- yes, this answer apparently worked for you. :-) – ruakh May 30 '19 at 15:32
  • OP is asking about the keystore, not the truststore. – user207421 Feb 07 '20 at 23:55
37

Just a word of caution. If you are trying to open an existing JKS keystore in Java 9 onwards, you need to make sure you mention the following properties too with value as "JKS":

javax.net.ssl.keyStoreType
javax.net.ssl.trustStoreType

The reason being that the default keystore type as prescribed in java.security file has been changed to pkcs12 from jks from Java 9 onwards.

Andy King
  • 1,632
  • 2
  • 20
  • 29
  • I haven't found that to be true; it seems to me that under JRE 11 I can provide either (somewhere in the maze of input to a Java KeyStore object) and it figures it out. That would be the sensible approach - to sniff the file and decide if it's jks or pkcs#12. – Arfur Narf Apr 18 '23 at 22:58
17

you can also mention the path at runtime using -D properties as below

-Djavax.net.ssl.trustStore=/home/user/SSL/my-cacerts 
-Djavax.net.ssl.keyStore=/home/user/SSL/server_keystore.jks

In my apache spark application, I used to provide the path of certs and keystore using --conf option and extraJavaoptions in spark-submit as below

--conf 'spark.driver.extraJavaOptions= 
-Djavax.net.ssl.trustStore=/home/user/SSL/my-cacerts 
-Djavax.net.ssl.keyStore=/home/user/SSL/server_keystore.jks' 
prayagupa
  • 30,204
  • 14
  • 155
  • 192
9

First of all, there're two kinds of keystores.

Individual and General

The application will use the one indicated in the startup or the default of the system.

It will be a different folder if JRE or JDK is running, or if you check the personal or the "global" one.

They are encrypted too

In short, the path will be like:

$JAVA_HOME/lib/security/cacerts for the "general one", who has all the CA for the Authorities and is quite important.

slm
  • 15,396
  • 12
  • 109
  • 124
Carlos Garcia
  • 233
  • 1
  • 6
0

On a M1 iMac system to import a key to use with Java or a IDE like jGRASP use command sudo keytool -importcert -keystore after path to java keystore example here and path to certificate you want to import in my example I have pfsense SSL certificate for use with the proxy and firewall.

sudo keytool -importcert -keystore /Library/Java/JavaVirtualMachines/jdk-19.jdk/Contents/Home/lib/security/cacerts -storepass changeit -file ~/Downloads/SquidCA.crt -alias "root_cert" /Library/Java/JavaVirtualMachines/jdk-19.jdk/Contents/Home/lib/security/cacerts

On a M1 iMAC to list what is in the certificate store for Java:

keytool -list -keystore "/Library/Java/JavaVirtualMachines/jdk-19.jdk/Contents/Home/lib/security/cacerts" Warning: use -cacerts option to access cacerts keystore

default password is changeit

After reinstall jGRASP or what IDE you use and it functions with java code like,

URL news = new URL("https://moxie.foxnews.com/feedburner/world.xml/");

BufferedReader in = new BufferedReader(new InputStreamReader(news.openStream())); Image: Java program running with trusted root SSL cert installed using https URL. URL seen in both proxy Pfsense Firewall and jGRASP IDE

again, yes Java JDK tools can work with SSL self signed certs.

It also works in Windows 11 just use Oracle's JDK kit path

C:\Program Files\Java\jdk-20\lib\security\cacerts

tool path

C:\Program Files\Java\jdk-20\bin\keytool

I just drop the cert I need into the folder named security and run similar commands as the imac just different paths.

Example: Windows 10 Example of Use

Java Root Cert Now added

What I like about this is when I am testing Java code with import statements the firewall can see any one offs or any http https get requests that occur that shouldn't in large source code. If something is hidden in an import item now the firewall can see it.