In my java application I need to send POST requests to a server sitting behind https. On the machine where my java application is running there is a java trust store in: /usr/local/comp.jks
that contains the certificate for the server I need to interact with (its already imported).
The problem is that I cannot control how the JVM is started that will run my java application - e.g. by adding:
-Djavax.net.ssl.trustStore=/usr/local/comp.jks
to the VM arguments.
Is it possible to load the trust store in the above path at runtime from my application after the JVM has started so I can authenticate against the https site?
I have only found guides on how to import certificates at runtime but that I cannot use - also since I don't have the password for /usr/local/comp.jks
Below my current implementation (in groovy):
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import java.util.Base64;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class HttpsClientImpl extends AbstractHttpClient {
private String username = null;
private String password = null;
public HttpsClientImpl (String username, String password) {
this.username=username;
this.password=password;
}
@Override
public String sendRequest(String request, String method) {
System.setProperty( "javax.net.ssl.trustStore", "/usr/local/comp.jks" );
URL url = new URL(request);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection()
// Set auth
byte[] name = (username + ":" + password).getBytes();
String authStr = Base64.getEncoder().encodeToString(name);
con.setRequestProperty("Authorization", "Basic " + authStr)
con.setRequestMethod(method);
writeResult(con);
return con.getResponseCode();
}
private void writeResult(HttpsURLConnection con) throws IOException {
if(con!=null){
BufferedReader br = null;
if (200 <= con.getResponseCode() && con.getResponseCode() <= 299) {
br = new BufferedReader(new InputStreamReader(con.getInputStream()));
} else {
br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
}
try {
String input;
while ((input = br.readLine()) != null){
System.out.println(input);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
When I run that I get:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
Caused: sun.security.validator.ValidatorException: PKIX path building failed
Assuming you haven't instantiated any SSL connections yet, you can simply call
System.setProperty( "javax.net.ssl.trustStore", "/usr/local/comp.jks" );
You'll probably also need to set javax.net.ssl.trustStorePassword
and maybe javax.net.ssl.trustStoreType
.
If the default SSL infrastructure has alredy been instantiated, you'll probably have to create your own SSLContext
and SSLSocketFactory
using your keystore.
You can do so by initializing key store like below:-
SSLContext sslContext = null;
String keyStorePath = "/usr/local/comp.jks";
String trustStorePath = "/usr/local/comp.jks";
String keyStorePw = "????";//put your key store password
String trustStorePw = "????";//put your truststore password
String keyPass = "????";//put your certificate key password
sslContext = initializeSSLContext(keyStorePath, keyStorePw, trustStorePath, trustStorePw, keyPass);
URL obj;
HttpsURLConnection conn = null;
try {
obj = new URL(null , url, new sun.net.www.protocol.https.Handler());
} catch (MalformedURLException e) {
System.out.println("MalformedURLException occurred " + e.getMessage());
}
conn=(HttpsURLConnection) obj.openConnection();
conn.setSSLSocketFactory(sslContext.getSocketFactory());
private SSLContext initializeSSLContext(final String keyStorePath, final String pwKeyStore, final String trustStorePath, final String pwTrustStore, final String keyPass, final boolean trustall) {
char[] keyStorePw = pwKeyStore.toCharArray();
char[] trustStorePw = pwTrustStore.toCharArray();
char[] keyPw = keyPass.toCharArray();
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextInt();
KeyStore ks = null;
try {
ks = KeyStore.getInstance("JKS");
} catch (KeyStoreException exp) {
System.out.println("SSLContextUtil::KeyStoreException exception occurred while reading the config file : " +exp.getMessage());
}
FileInputStream fis = null;
try {
try {
fis = new FileInputStream(keyStorePath);
} catch (FileNotFoundException exp) {
System.out.println("SSLContextUtil::FileNotFoundException exception occurred " +exp.getMessage());
}
try {
ks.load(fis, keyStorePw);
} catch (NoSuchAlgorithmException exp) {
System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
} catch (CertificateException exp) {
System.out.println("SSLContextUtil::CertificateException exception occurred " +exp.getMessage());
} catch (IOException exp) {
System.out.println("SSLContextUtil::CertificateException exception occurred " +exp.getMessage());
}
} finally {
if (fis != null)
try {
fis.close();
} catch (IOException exp) {
System.out.println("SSLContextUtil::IOException exception occurred " +exp.getMessage());
}
}
System.out.println.info("SSLContextUtil::[initializeSSLContext] KMF keystorepw loaded.");
KeyManagerFactory kmf = null;
try {
kmf = KeyManagerFactory.getInstance("SunX509");
} catch (NoSuchAlgorithmException exp) {
System.out.println("SSLContextUtil::IOException exception occurred " +exp.getMessage());
}
try {
kmf.init(ks, keyPw);
} catch (UnrecoverableKeyException exp) {
System.out.println("SSLContextUtil::UnrecoverableKeyException exception occurred " +exp.getMessage());
} catch (KeyStoreException exp) {
System.out.println("SSLContextUtil::KeyStoreException exception occurred " +exp.getMessage());
} catch (NoSuchAlgorithmException exp) {
System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
}
System.out.println.info("SSLContextUtil::[initializeSSLContext] KMF init done.");
KeyStore ts = null;
try {
ts = KeyStore.getInstance("JKS");
} catch (KeyStoreException exp) {
System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
}
FileInputStream tfis = null;
SSLContext sslContext = null;
try {
tfis = new FileInputStream(trustStorePath);
ts.load(tfis, trustStorePw);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ts);
System.out.println.info("SSLContextUtil::[initializeSSLContext] Truststore initialized");
sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers() ,secureRandom);
} catch (NoSuchAlgorithmException exp) {
System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
} catch (CertificateException exp) {
System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
} catch (IOException exp) {
System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
} catch (KeyStoreException exp) {
System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
} catch (KeyManagementException exp) {
System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
} finally {
if (tfis != null)
try {
tfis.close();
} catch (IOException exp) {
System.out.println("SSLContextUtil::NoSuchAlgorithmException exception occurred " +exp.getMessage());
}
}
if((sslContext == null)){
System.out.println("SSLContextUtil::[initializeSSLContext] sslContext is null");
}
return sslContext;
}