I have two .cer files (one for client and other from server). I need to configure a docker container running a java spring boot app.
I'm a little confused with identity.jks, truststore.jks, client.cer and server.cer. In my POC (no docker) I generate all from scratch, by example:
Step 1) Generate public/private key for client
keytool -v -genkeypair -dname "CN=Willams,OU=Brasil,O=Dev,C=BR" -keystore ./identity.jks -storepass secret -keypass secret -keyalg RSA -keysize 2048 -alias client -validity 3650 -deststoretype pkcs12 -ext KeyUsage=digitalSignature,dataEncipherment,keyEncipherment,keyAgreement -ext ExtendedKeyUsage=serverAuth,clientAuth
Step 2) Create client certificate
keytool -v -exportcert -file ./client.cer -alias client -keystore ./identity.jks -storepass secret -rfc
Step 3) Include server certificate at truststore
keytool -v -importcert -file ./server.cer -alias server -keystore ./truststore.jks -storepass secret -noprompt
But how make the same thing, but using existing .cer (client and server) and a docker container?
My WebClient Code actual is:
#Value("${client.ssl.one-way-authentication-enabled:false}") boolean oneWayAuthenticationEnabled;
#Value("${client.ssl.two-way-authentication-enabled:false}") boolean twoWayAuthenticationEnabled;
#Value("${client.ssl.key-store:}") String keyStorePath;
#Value("${client.ssl.key-store-password:}") char[] keyStorePassword;
#Value("${client.ssl.trust-store:}") String trustStorePath;
#Value("${client.ssl.trust-store-password:}") char[] trustStorePassword;
#Bean
public WebClient webClientFe() throws SSLException {
HttpClient httpClient = HttpClient.create()
.secure(sslSpec -> sslSpec.sslContext(getTwoWaySslContext()));
return WebClient
.builder()
.uriBuilderFactory(getBaseFeUri())
.defaultHeader(HEADER_CACHE_CONTROL, HEADER_CACHE_CONTROL_VALUE)
.baseUrl(SERVER_URL)
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
private DefaultUriBuilderFactory getBaseFeUri() {
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(SERVER_URL);
factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
return factory;
}
private SslContext getTwoWaySslContext() {
try(FileInputStream keyStoreFileInputStream = new FileInputStream(ResourceUtils.getFile(keyStorePath));
FileInputStream trustStoreFileInputStream = new FileInputStream(ResourceUtils.getFile(trustStorePath));
) {
KeyStore keyStore = KeyStore.getInstance("jks");
keyStore.load(keyStoreFileInputStream, keyStorePassword);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyStorePassword);
KeyStore trustStore = KeyStore.getInstance("jks");
trustStore.load(trustStoreFileInputStream, trustStorePassword);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
return SslContextBuilder.forClient()
.keyManager(keyManagerFactory)
.trustManager(trustManagerFactory)
.build();
} catch (Exception e) {
log.error("An error has occurred: ", e);
}
return null;
}
Related
I'm using the following to initialize an HTTPS driven server for a secure website. The keystore command is as follows:
keytool -genkey -keyalg RSA -alias mykey -keystore keystore.jks -keypass password -storepass password -validity 365 -keysize 2048
After running the code I get a bad_certificate error message when I attempt to load my website and a yellow screen appears. What am I doing wrong?
String path = "C:\\Users\\Administrator\\Documents\\NetBeansProjects\\SSLTest5";
String file = path + "\\" + "keystore.jks";
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream(file),"password".toCharArray());
// Create key manager
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, "password".toCharArray());
KeyManager[] km = keyManagerFactory.getKeyManagers();
// Create trust manager
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
trustManagerFactory.init(keyStore);
TrustManager[] tm = trustManagerFactory.getTrustManagers();
// Initialize SSLContext
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(km, tm, null);
SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(443);
System.out.println("Waiting for client...");
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
HandleAccept(sslSocket);
I have the client certs and the CA cert and I followed this tutorial to generate the corresponding p12 file and the jks file.
I ran these commands to generate the above files:
openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -name "pandb_client" --> this gave me client.p12 file
keytool -genkey -dname "cn=CLIENT" -alias storekey -keyalg RSA -keystore ./store.jks -keypass changeit -storepass changeit --> this gave me the store.jks
keytool -import -keystore ./store.jks -file ca.crt -alias client --> i imported the CA into newly created JKS
Here is the code:
import okhttp3.*;
import org.apache.http.ssl.SSLContexts;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.*;
import java.security.cert.CertificateException;
import java.time.Duration;
final class ConnectUsingSSL {
private static final String CA_KEYSTORE_TYPE = KeyStore.getDefaultType(); //"JKS";
private static final String CA_KEYSTORE_PATH = "store.jks";
private static final String CA_KEYSTORE_PASS = "changeit";
private static final String CLIENT_KEYSTORE_TYPE = "PKCS12";
private static final String CLIENT_KEYSTORE_PATH = "client.p12";
private static final String CLIENT_KEYSTORE_PASS = "changeit";
public static void main(String[] args) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, KeyManagementException, UnrecoverableKeyException {
SSLContext context = createSslCustomContext();
final OkHttpClient okHttpClient = new OkHttpClient.Builder().
readTimeout(Duration.ofMillis(60000L)).
connectTimeout(Duration.ofMillis(60000L)).
callTimeout(Duration.ofMillis(60000L)).
retryOnConnectionFailure(Boolean.TRUE).
sslSocketFactory(context.getSocketFactory(), (X509TrustManager) getTrustManager()[0]).
hostnameVerifier((hostname, session) -> true).
build();
RequestBody requestBody = RequestBody.create("{\"query\": {\"urls\": [\"google.com\", \"yahoo.com\", \"facebook.com\"]}}",
MediaType.parse("application/json; charset=utf-8"));
Request request = new Request.Builder().
url("https://somehost:443/query_urls").
post(requestBody).
build();
try (Response response = okHttpClient.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response.body().string());
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
private static SSLContext createSslCustomContext() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException {
// Trusted CA keystore
KeyStore tks = KeyStore.getInstance(CA_KEYSTORE_TYPE);
tks.load(new FileInputStream(CA_KEYSTORE_PATH), CA_KEYSTORE_PASS.toCharArray());
// Client keystore
KeyStore cks = KeyStore.getInstance(CLIENT_KEYSTORE_TYPE);
cks.load(new FileInputStream(CLIENT_KEYSTORE_PATH), CLIENT_KEYSTORE_PASS.toCharArray());
return SSLContexts.custom()
.loadKeyMaterial(cks, CLIENT_KEYSTORE_PASS.toCharArray())
.build();
}
private static TrustManager[] getTrustManager() throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
// Trusted CA keystore
KeyStore tks = KeyStore.getInstance(CA_KEYSTORE_TYPE);
tks.load(new FileInputStream(CA_KEYSTORE_PATH), CA_KEYSTORE_PASS.toCharArray());
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(tks);
return tmf.getTrustManagers();
}
}
I have spent more than 7 hours trying to make this work, however I have failed any help is highly appreciated.
Response from the server:
java.io.IOException: Unexpected code <html>
<head><title>400 No required SSL certificate was sent</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>nginx/1.12.2</center>
</body>
</html>
import socket
import ssl
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.SSLSocket(sock=s, ssl_version=ssl.PROTOCOL_TLSv1,
certfile="client.crt", keyfile="client.key",
server_hostname="queryurls")
ssl_sock.connect(("somehost", 443))
body = '{"query": {"urls": ["google.com", "yahoo.com", "facebook.com"]}}'
rqst = "POST /query_urls HTTP/1.1\r\nHost: queryurls\r\nContent-Type: application/json\r\nContent-Length: %d\r\nConnection: keep-alive\r\n\r\n%s" % (len(body), body)
ssl_sock.sendall(rqst)
#you should process the HTTP reply header to retrieve the reply body length
#and keep reading until you receive the full reply body.
print rqst
reply = ssl_sock.recv(16384);
print reply
The same client certificate and CA works perfectly fine when I run the above Python code, not sure how to replicate it in JAVA.
I am trying to make a two way SSL authentication to a server.
The server has SSL implemented to I need to make a HTTPS connection to the server. The server is with a third party vendor so i don't have server access. Although they have given me a server certificate test.crt.
Then I created my own self signed certificate by following the following commands.
generating keystore
keytool -genkey -alias myssl -keystore /home/user/mykey.keystore -validity 365
generating cer file
keytool -export -alias myssl -keystore /home/user/mykey.keystore -file /home/user/mykey.cer
import the cer file into the bks file
keytool -import -alias test_cer -file /home/user/mykey.cer -keystore /home/user/mykey.bks -storetype BKS -providerClass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath /home/user/bcprov-jdk15on-146.jar
Now I have 3 files : mykey.keystore, mykey.cer and mykey.bks.
So i gave the .cer file to the server vendors and they imported the certificate into their truststore.
Now, in my android application I try to connect to the server. I put the certificate from the server test.crt into the trust store and my mykey.cer into the key store and pass the trust manager and the key manager into the SSLContext.
Below is the relevant code.
allowTrustedSSL(this.activity);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(method,url,dataToSend, onResponseListener,onErrorListener);
/**
* Method implements self-signed certificates
* #param context
*/
public static void allowTrustedSSL(Context context){
/**
* We shall accept traffic with any host names
*/
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
Logger.d(TAG, "verify() called with: hostname = [" + hostname + "], session = [" + session + "]");
return true;
}
});
try{
//the NoSSLv3SocketFactory will disable the SSLv3
SSLSocketFactory noSSLv3Factory = new NoSSLv3SocketFactory(sslSocketFactoryGenerator(context));
HttpsURLConnection.setDefaultSSLSocketFactory(noSSLv3Factory);
} catch (Exception e) {
Logger.e(TAG, "allowTrustedSSL: "+e.getMessage());
e.printStackTrace();
}
}
public static SSLSocketFactory sslSocketFactoryGenerator(Context context) throws
UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException,
KeyStoreException, IOException, KeyManagementException {
//the test.crt file
TrustManagerFactory trustManagerFactory = getTrustManagerFactory(context.getResources().openRawResource(R.raw.test));
//the mykey.cer file
KeyManagerFactory keyManagerFactory = getKeyManagerFactory(context.getResources().openRawResource(R.raw.mykey),
MYKEY_PASS.toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(),null);
return sslContext.getSocketFactory();
}
public static TrustManagerFactory getTrustManagerFactory(InputStream fileInput) throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException {
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate ca;
try {
ca = cf.generateCertificate(fileInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
fileInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
return tmf;
}
public static KeyManagerFactory getKeyManagerFactory(InputStream fileInput,char[] password)
throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate ca;
try {
ca = cf.generateCertificate(fileInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
fileInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String keyManAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(keyManAlgorithm);
keyManagerFactory.init(keyStore, password);
return keyManagerFactory;
}
But when i start the connection to the server all I am getting is SSLException: Connection closed by peer. I have googled a lot for a proper documentation or example for implementing the two way ssl from android. And I have lost many precious days on figuring it out on myself.
Is my process of creating the certificates incorrect?
After reading through numerous answers concerning these topics, I have found myself completely unable to string together the pieces of the puzzle, I hope you will excuse me for this.
I am trying to change my simple socket connection in Java to use SSL. I would like both the server and client to authenticate themselves if possible, but only server authentication would be good start.
Currently, this is the extremely simple code on the server side:
ServerSocket serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
And this is the code on the client side:
Socket socket = null;
while (true) {
try {
socket = new Socket(ipAddress, port);
break;
} catch (Exception e) {}
}
This works fine, but without SSL.
I have generated SSL certificates for the server and client using OpenSSL, ending up with:
A certificate for the server (PEM format)
A certificate for the client (PEM format)
A private key for the server (PEM format)
A private key for the client (PEM format)
A CA file (PEM, CER and CRT format)
From this I have used OpenSSL to create PKCS12 (.p12) keystores for both the client and the server, as follows
server.p12, made by doing openssl pkcs12 -export -in server-cert.pem -inkey server-private-key.pem -out server.p12
client.p12, made by doing openssl pkcs12 -export -in client-cert.pem -inkey client-private-key.pem -out client.p12
Then, I turned these into JKS keystores by using keytool (for the server, for example, the command was keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -destkeystore server.jks -deststoretype JKS), resulting in two files named server.jks and client.jks.
I then use the following code as replacement for the previous server snippet:
char[] keyStorePassword = "JKSPassword".toCharArray();
FileInputStream keyStoreFile = new FileInputStream("somepath/server.jks");
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(keyStoreFile, keyStorePassword);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "PKCS12Password".toCharArray());
SSLContext sslContext = SSLContext.getDefault();
ServerSocket serverSocket = sslContext.getServerSocketFactory().createServerSocket(port);
Socket socket = serverSocket.accept();
And the following code as replacement for the client snippet:
Socket socket = null;
while (true) {
try {
char[] keyStorePassword = "JKSPassword".toCharArray();
FileInputStream keyStoreFile = new FileInputStream("somepath/client.jks");
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(keyStoreFile, keyStorePassword);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "PKCS12Password".toCharArray());
SSLContext sslContext = SSLContext.getDefault();
socket = sslContext.getSocketFactory().createSocket(ipAddress, port);
break;
} catch (Exception e) {}
}
I now still get javax.net.ssl.SSLHandshakeException: no cipher suites in common on the server (and javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure on the client).
What could be wrong?
I found the missing part of the puzzle (I believe).
Instead of the line SSLContext sslContext = SSLContext.getDefault(); on the client, I put:
BufferedInputStream serverCertificateFile = new BufferedInputStream(new FileInputStream("somepath/server-cert.der"));
X509Certificate serverCertificate = (X509Certificate)
CertificateFactory.getInstance("X.509").generateCertificate(serverCertificateFile);
sslContext.init(keyManagerFactory.getKeyManagers(), new TrustManager[] {
new X509TrustManager() {
#Override
public void checkClientTrusted(X509Certificate[] arg0,
String arg1) throws CertificateException {
throw new CertificateException();
}
#Override
public void checkServerTrusted(X509Certificate[] arg0,
String arg1) throws CertificateException {
boolean valid = false;
for (X509Certificate certificate : arg0) {
try {
certificate.verify(serverCertificate.getPublicKey());
valid = true;
break;
} catch (SignatureException e) {}
}
if (!valid) {
throw new CertificateException();
}
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
}, new SecureRandom());
server-cert.der is a file, created with openssl509 -outform der -in server-cert.pem -out server-cert.der.
I was not able to find good tutorials or question on this matter on StackOverflow, so this is what I created by attempting to understand the reference guide.
Essentially, I am creating a TrustManager that, for a server, trusts it when one of the provided certificates is the one that belongs to your own server.
It appears to work, please let me know if there is anything principally wrong with this approach (I unfortunately assume there is). Thanks for having read so much!
Using HttpClient, I receive the following error when attempting to communicate over HTTPS:
Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated.
Here is my code:
URI loginUri = new URI("https://myUrl.asp");
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet( loginUri );
HttpResponse response = httpclient.execute( httpget );
How do I suppress or remove this error?
Note: Do not do this in production code, use http instead, or the actual self signed public key as suggested above.
On HttpClient 4.xx:
import static org.junit.Assert.assertEquals;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.junit.Test;
public class HttpClientTrustingAllCertsTest {
#Test
public void shouldAcceptUnsafeCerts() throws Exception {
DefaultHttpClient httpclient = httpClientTrustingAllSSLCerts();
HttpGet httpGet = new HttpGet("https://host_with_self_signed_cert");
HttpResponse response = httpclient.execute( httpGet );
assertEquals("HTTP/1.1 200 OK", response.getStatusLine().toString());
}
private DefaultHttpClient httpClientTrustingAllSSLCerts() throws NoSuchAlgorithmException, KeyManagementException {
DefaultHttpClient httpclient = new DefaultHttpClient();
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, getTrustingManager(), new java.security.SecureRandom());
SSLSocketFactory socketFactory = new SSLSocketFactory(sc);
Scheme sch = new Scheme("https", 443, socketFactory);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
return httpclient;
}
private TrustManager[] getTrustingManager() {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
#Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
#Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
// Do nothing
}
#Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
// Do nothing
}
} };
return trustAllCerts;
}
}
This answer follows on to owlstead and Mat's responses. It applies to SE/EE installations, not ME/mobile/Android SSL.
Since no one has yet mentioned it, I'll mention the "production way" to fix this:
Follow the steps from the AuthSSLProtocolSocketFactory class in HttpClient to update your trust store & key stores.
Import a trusted certificate and generate a truststore file
keytool -import -alias "my server cert" -file server.crt -keystore my.truststore
Generate a new key (use the same password as the truststore)
keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore
Issue a certificate signing request (CSR)
keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore
(self-sign or get your cert signed)
Import the trusted CA root certificate
keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore
Import the PKCS#7 file containg the complete certificate chain
keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore
Verify the resultant keystore file's contents
keytool -list -v -keystore my.keystore
If you don't have a server certificate, generate one in JKS format, then export it as a CRT file. Source: keytool documentation
keytool -genkey -alias server-alias -keyalg RSA -keypass changeit
-storepass changeit -keystore my.keystore
keytool -export -alias server-alias -storepass changeit
-file server.crt -keystore my.keystore
Using HttpClient 3.x, you need to do this:
Protocol easyHttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
Protocol.registerProtocol("https", easyHttps);
An implementation of EasySSLProtocolSocketFactory can be found here.
This exception will come in case your server is based on JDK 7 and your client is on JDK 6 and using SSL certificates. In JDK 7 sslv2hello message handshaking is disabled by default while in JDK 6 sslv2hello message handshaking is enabled. For this reason when your client trying to connect server then a sslv2hello message will be sent towards server and due to sslv2hello message disable you will get this exception. To solve this either you have to move your client to JDK 7 or you have to use 6u91 version of JDK. But to get this version of JDK you have to get the
Method returning a "secureClient" (in a Java 7 environnement - NetBeans IDE and GlassFish Server: port https by default 3920 ), hope this could help :
public DefaultHttpClient secureClient() {
DefaultHttpClient httpclient = new DefaultHttpClient();
SSLSocketFactory sf;
KeyStore trustStore;
FileInputStream trustStream = null;
File truststoreFile;
// java.security.cert.PKIXParameters for the trustStore
PKIXParameters pkixParamsTrust;
KeyStore keyStore;
FileInputStream keyStream = null;
File keystoreFile;
// java.security.cert.PKIXParameters for the keyStore
PKIXParameters pkixParamsKey;
try {
trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
truststoreFile = new File(TRUSTSTORE_FILE);
keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keystoreFile = new File(KEYSTORE_FILE);
try {
trustStream = new FileInputStream(truststoreFile);
keyStream = new FileInputStream(keystoreFile);
} catch (FileNotFoundException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
}
try {
trustStore.load(trustStream, PASSWORD.toCharArray());
keyStore.load(keyStream, PASSWORD.toCharArray());
} catch (IOException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
} catch (CertificateException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
}
try {
pkixParamsTrust = new PKIXParameters(trustStore);
// accepts Server certificate generated with keytool and (auto) signed by SUN
pkixParamsTrust.setPolicyQualifiersRejected(false);
} catch (InvalidAlgorithmParameterException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
}
try {
pkixParamsKey = new PKIXParameters(keyStore);
// accepts Client certificate generated with keytool and (auto) signed by SUN
pkixParamsKey.setPolicyQualifiersRejected(false);
} catch (InvalidAlgorithmParameterException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
}
try {
sf = new SSLSocketFactory(trustStore);
ClientConnectionManager manager = httpclient.getConnectionManager();
manager.getSchemeRegistry().register(new Scheme("https", 3920, sf));
} catch (KeyManagementException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
} catch (UnrecoverableKeyException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
} catch (KeyStoreException ex) {
Logger.getLogger(ApacheHttpRestClient.class.getName()).log(Level.SEVERE, null, ex);
}
// use the httpclient for any httpRequest
return httpclient;
}
Your local JVM or remote server may not have the required ciphers. go here
https://www.oracle.com/java/technologies/javase-jce8-downloads.html
and download the zip file that contains:
US_export_policy.jar
and
local_policy.jar
replace the existing files (you need to find the existing path in your JVM).
on a Mac, my path was here.
/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/security
this worked for me.