Java import certificate to trust store

HTTPS request with trust store for server certificates

HTTPS requests in the JVM must use a trust store to validate the origin of the presented server certificate when the TLS connection is made. The JVM ships with a default trust store containing a set of root certificates, potentially with intermediates, of popular approved certificate authorities (CA), such as Let’s Encrypt.

On a Linux distribution the default trust store file may be found in the following location and can be inspected with the keytool utility or programmatically via the KeyStore class:

If the web server presents a certificate issued and signed by a CA which root certificate is found in the trust store the HTTPS connection will succeed.

If not the request from your Java client will fail with an exception similar to this one:

javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 

Supporting other CAs

If the web server has a certificate issued by a CA which root certificate isn’t found in the default Java trust store, or the certificate is self-issued, you have three options:

  1. Update the default trust store Add the CA root certificate or the server certificate (if self-issued) to the default trust store. This may require administrator privileges. Check out our article which explains the steps.
  2. Switch to a new default trust store Create a new trust store with keytool and import the CA root certificate into it. Then instruct your Java application to use the new trust store as the default one with the following system property:
javax.net.ssl.trustStore=/path/to/my/truststore.jks 

Configure a custom trust store for each HTTPS request

In order to create a TLS connection with a custom trust store Java needs to be provided a specially configured SSLSocketFactory.

The TLSUtility which is part of this SDK since v7.1 simplifies the task.

Suppose your application needs to make token requests and the OAuth 2.0 server is issued with a certificate from a CA which is not present the default trust store.

CA certificate(s) in trust store file

Import the CA certificate into a new trust store file and then use it with each HTTPS connection like this:

import java.io.*; import java.security.KeyStore; import javax.net.ssl.SSLSocketFactory; import com.nimbusds.oauth2.sdk.*; import com.nimbusds.oauth2.sdk.http.*; import com.nimbusds.oauth2.sdk.util.tls.*; // The trust store file and optional password to unlock it File trustStoreFile = new File("/path/to/my/truststore.jks"); char[] trustStorePassword = null; // assuming no trust store password // Load the trust store, the default type is "pkcs12", the alternative is "jks" KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(new FileInputStream(trustStoreFile), trustStorePassword); // Create a new SSLSocketFactory, you can keep it around for each HTTPS // request as it's thread-safe. Use the most recent TLS version supported by // the web server. TLS 1.3 has been standard since 2018 and is recommended. SSLSocketFactory sslSocketFactory = TLSUtils.createSSLSocketFactory( trustStore, TLSVersion.TLS_1_3); // Create your token request the usual way TokenRequest tokenRequest = new TokenRequest(. ); HTTPRequest httpRequest = tokenRequest.toHTTPRequest(); // Set the SSLSocketFactory with the configured trust store httpRequest.setSSLSocketFactory(sslSocketFactory); // Proceed with the request as usual HTTPResponse httpResponse = httpRequest.send(); System.out.println(httpResponse.getStatusCode()); 

CA certificate(s) in PEM file

If the CA certificate(s) (or the self-issued server certificate) was supplied in the ubiquitous ASCII-encoded PEM format and you don’t want to deal with setting up a trust store:

import java.io.*; import java.security.KeyStore; import javax.net.ssl.SSLSocketFactory; import com.nimbusds.jose.util.*; import com.nimbusds.oauth2.sdk.*; import com.nimbusds.oauth2.sdk.http.*; import com.nimbusds.oauth2.sdk.util.tls.*; // The PEM file with one or more CA root and potentially // intermediate certificates, can also contain just the // server's certificate (self-issued or not) File pemFile = new File("/path/to/my/caCerts.pem"); // Parse the X.509 certificates from the PEM file List caCerts = X509CertChainUtils.parse(pemFile); // Create an in-memory trust store and put the // certificates in it KeyStore trustStore = KeyStore.getInstance("jks"); trustStore.load(null); X509CertChainUtils.store(trustStore, caCerts); // Create a new SSLSocketFactory, you can keep it around for each HTTPS // request as it's thread-safe. Use the most recent TLS version supported by // the web server. TLS 1.3 has been standard since 2018 and is recommended. SSLSocketFactory sslSocketFactory = TLSUtils.createSSLSocketFactory( trustStore, TLSVersion.TLS_1_3); // Create your token request the usual way TokenRequest tokenRequest = new TokenRequest(. ); HTTPRequest httpRequest = tokenRequest.toHTTPRequest(); // Set the SSLSocketFactory with the configured trust store httpRequest.setSSLSocketFactory(sslSocketFactory); // Proceed with the request as usual HTTPResponse httpResponse = httpRequest.send(); System.out.println(httpResponse.getStatusCode()); 

How to debug TLS connections

Simply set the following Java system property and this will print the TLS handshake for each connection to the console:

javax.net.debug=ssl,handshake 

For example, this will print the certificate chain presented by the web server:

"Certificates": [ "certificate" : < "version" : "v3", "serial number" : "03 6E AC 75 C6 00 99 6A D3 4A 69 F6 93 F3 FD 34 F2 75", "signature algorithm": "SHA256withRSA", "issuer" : "CN=Let's Encrypt Authority X3, O=Let's Encrypt, C=US", "not before" : "2020-02-13 19:24:37.000 EET", "not after" : "2020-05-13 20:24:37.000 EEST", "subject" : "CN=demo.c2id.com", "subject public key" : "RSA", "extensions" : [ "more data . " ] >, "certificate" : < "version" : "v3", "serial number" : "0A 01 41 42 00 00 01 53 85 73 6A 0B 85 EC A7 08", "signature algorithm": "SHA256withRSA", "issuer" : "CN=DST Root CA X3, O=Digital Signature Trust Co.", "not before" : "2016-03-17 18:40:46.000 EET", "not after" : "2021-03-17 18:40:46.000 EET", "subject" : "CN=Let's Encrypt Authority X3, O=Let's Encrypt, C=US", "subject public key" : "RSA", "extensions" : [ "more data . " ] >] 

Источник

Import the Certificate as a Trusted Certificate

Before you can grant the signed code permission to read a specified file, you need to import Susan’s certificate as a trusted certificate in your keystore.

Suppose that you have received from Susan

  • the signed JAR file sCount.jar , which contains the Count.class file, and
  • the file Example.cer , which contains the public key certificate for the public key corresponding to the private key used to sign the JAR file.

Even though you created these files and they haven’t actually been transported anywhere, you can simulate being someone other than the creator and sender, Susan. Pretend that you are now Ray. Acting as Ray, you will create a keystore named exampleraystore and will use it to import the certificate into an entry with an alias of susan .

A keystore is created whenever you use a keytool command specifying a keystore that doesn’t yet exist. Thus we can create the exampleraystore and import the certificate via a single keytool command. Do the following in your command window.

  1. Go to the directory containing the public key certificate file Example.cer . (You should actually already be there, since this lesson assumes that you stay in a single directory throughout.)
  2. Type the following command on one line:
keytool -import -alias susan -file Example.cer -keystore exampleraystore 

Since the keystore doesn’t yet exist, it will be created, and you will be prompted for a keystore password; type whatever password you want.

The keytool command will print out the certificate information and ask you to verify it, for example, by comparing the displayed certificate fingerprints with those obtained from another (trusted) source of information. (Each fingerprint is a relatively short number that uniquely and reliably identifies the certificate.) For example, in the real world you might call up Susan and ask her what the fingerprints should be. She can get the fingerprints of the Example.cer file she created by executing the command

keytool -printcert -file Example.cer 

If the fingerprints she sees are the same as the ones reported to you by keytool , the certificate has not been modified in transit. In that case you let keytool proceed with placing a trusted certificate entry in the keystore. The entry contains the public key certificate data from the file Example.cer and is assigned the alias susan .

Previous page: Observe the Restricted Application
Next page: Set Up a Policy File to Grant the Required Permission

Источник

How to import a CA root certificate into the JVM trust store

Web browsers and application runtimes, such as Java, have a special local database of recognised Certificate Authorities (CA). Each time an SSL/TLS connection is made, that database is queried in order to validate a server’s claimed identity (typically represented by its domain name).

If you try to make a secure connection (e.g. HTTPS or LDAPS) and the server doesn’t respond with a certificate issued by a recognised authority, the connection will fail with the following exception:

CertPathBuilderException: unable to find valid certification path to requested target 

If your company has its own CA, or, if you want to make SSL/TLS connections to a server in possession of a certificate issued by a CA which you recognise and trust, but is not listed in the default Java trust store, you will need to import the CA’s root certificate.

We recently encountered such a case when a user of the online OpenID Connect client was not able to connect to a web server which has a certificate issued by the StartCom CA. The root certificate of StartCom is recognised by browsers, but for some reason has not been included in the default JVM trust store.

Instructions for importing a CA root certificate into the JVM trust store

Step 1. Obtain the root certificate

For StartCom the root certificate was made available at http://www.startssl.com/certs/ca.pem, in PEM format. Certificates contain public information and CAs always make them available for download.

Step 2. Convert the root certificate to DER format

This can be done with help of the openssl toolkit, where ca.pem is the original certificate filename in PEM format, and ca.der the filename to output, in DER format (which the Java keytool utility can understand). If you were able to obtain the root certificate in DER format, skip this step.

openssl x509 -in ca.pem -inform pem -out ca.der -outform der 

Step 3. Validate the root certificate content

Ensure that the Java keytool can parse the certificate and display its content:

keytool -v -printcert -file ca.der 

Step 4. Import the root certificate into the JVM trust store

Enter the following command where $JAVA_HOME is a shell environment variable that points to your Java installation, e.g. to /usr/lib/jvm/java-7-oracle ; for -alias pick some unique name for the certificate in the store:

keytool -importcert -alias startssl -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -file ca.der 

(the default password for the CA store is changeit )

The keytool will prompt you for confirmation, enter yes to complete the operation.

Step 5. Verify that the root certificate has been imported

To do that list the trust store content and filter for the certificate alias (name) with grep :

keytool -keystore "$JAVA_HOME/jre/lib/security/cacerts" -storepass changeit -list | grep startssl 

You will now be able to make secure SSL/TLS connections to servers which have a certificate signed by the CA which we just imported.

Источник

Читайте также:  Java load all resources
Оцените статью