Cassandra C# TLS version selection? - ssl

How can I select different version of TLS for secure client connection to Apache Cassandra cluster. The cluster is running Cassandra version 4.0. The client application is using Datastax driver for C#. My cluster builder code looks similar to this (I've cleaned-up real user, password, IPs etc.):
Cluster.Builder().WithCredentials("keyspaceUser", "keyspacePassword")
.AddContactPoints("127.0.0.1, 128.0.0.1, 129.0.0.1")
.WithSSL(new SSLOptions()
.SetCertificateCollection(new X509Certificate2Collection
{
new X509Certificate2(certPath, "certificatePassword")
}
)
.SetRemoteCertValidationCallback(
(sender, certificate, chain, errors) => { return true; }
)
)
.WithLoadBalancingPolicy(new RoundRobinPolicy())
.Build();
The problem I am facing which I can see in Cassandra's system.log is:
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: error:100000f0:SSL routines:OPENSSL_internal:UNSUPPORTED_PROTOCOL
After further analysis I could find that the client is trying to use TLSv1 which is obsolete and by default disabled in Java 1.8.
So my question is how I can set in the builder to use different TLS version?
Thanks

The SSLOptions type has a constructor that allows you to specify which ssl protocol to use.

Related

Jetty SSL problem after upgrade - unknown protocol

I upgraded Jetty 9.3.6 to Jetty 9.4.27 and I have a problem with SSL connection.
When I run curl on some supported operation I get
error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol (error 35) whereas when I run the same command on the server running Jetty 9.3.6 it is all working fine.
I configured jetty's newer version in the same way as was the older one (including keystore path and enabling https support). Do you have a clue what could have gone wrong during upgrade or what I could have missed?
Thanks a lot for your support.
Jetty 9.3.x and 9.4.x have different Cipher Suite exclusions.
Jetty 9.3.6.v20151106 looks like this ...
https://github.com/eclipse/jetty.project/blob/jetty-9.3.6.v20151106/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java#L248-L260
addExcludeProtocols("SSL", "SSLv2", "SSLv2Hello", "SSLv3");
setExcludeCipherSuites(
"SSL_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_DSS_WITH_DES_CBC_SHA",
"SSL_RSA_EXPORT_WITH_RC4_40_MD5",
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
Jetty 9.4.29.v20200521 looks like this ...
https://github.com/eclipse/jetty.project/blob/jetty-9.4.29.v20200521/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java#L119-L138
/**
* Default Excluded Protocols List
*/
private static final String[] DEFAULT_EXCLUDED_PROTOCOLS = {"SSL", "SSLv2", "SSLv2Hello", "SSLv3"};
/**
* Default Excluded Cipher Suite List
*/
private static final String[] DEFAULT_EXCLUDED_CIPHER_SUITES = {
// Exclude weak / insecure ciphers
"^.*_(MD5|SHA|SHA1)$",
// Exclude ciphers that don't support forward secrecy
"^TLS_RSA_.*$",
// The following exclusions are present to cleanup known bad cipher
// suites that may be accidentally included via include patterns.
// The default enabled cipher list in Java will not include these
// (but they are available in the supported list).
"^SSL_.*$",
"^.*_NULL_.*$",
"^.*_anon_.*$"
};
You'll want to evaluate why you need known vulnerable cipher suites to function.
Also, if you are using an IBM JVM all bets are off, because the IBM uses non-standard Cipher Suite names (unlike all other JVMs that use the RFC Registered Cipher Suite names).

Jenkins checkout ERROR: svn: E175002: javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair [duplicate]

When I make an SSL connection with some IRC servers (but not others - presumably due to the server's preferred encryption method) I get the following exception:
Caused by: java.lang.RuntimeException: Could not generate DH keypair
at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:106)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverKeyExchange(ClientHandshaker.java:556)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:183)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
... 3 more
Final cause:
Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)
at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DashoA13*..)
at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:627)
at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:100)
... 10 more
An example of a server that demonstrates this problem is aperture.esper.net:6697 (this is an IRC server). An example of a server that does not demonstrate the problem is kornbluth.freenode.net:6697. [Not surprisingly, all servers on each network share the same respective behaviour.]
My code (which as noted does work when connecting to some SSL servers) is:
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new SecureRandom());
s = (SSLSocket)sslContext.getSocketFactory().createSocket();
s.connect(new InetSocketAddress(host, port), timeout);
s.setSoTimeout(0);
((SSLSocket)s).startHandshake();
It's that last startHandshake that throws the exception. And yes there is some magic going on with the 'trustAllCerts'; that code forces the SSL system not to validate certs. (So... not a cert problem.)
Obviously one possibility is that esper's server is misconfigured, but I searched and didn't find any other references to people having problems with esper's SSL ports, and 'openssl' connects to it (see below). So I'm wondering if this is a limitation of Java default SSL support, or something. Any suggestions?
Here's what happens when I connect to aperture.esper.net 6697 using 'openssl' from commandline:
~ $ openssl s_client -connect aperture.esper.net:6697
CONNECTED(00000003)
depth=0 /C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support#esper.net
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support#esper.net
verify return:1
---
Certificate chain
0 s:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support#esper.net
i:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support#esper.net
---
Server certificate
-----BEGIN CERTIFICATE-----
[There was a certificate here, but I deleted it to save space]
-----END CERTIFICATE-----
subject=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support#esper.net
issuer=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support#esper.net
---
No client certificate CA names sent
---
SSL handshake has read 2178 bytes and written 468 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-AES256-SHA
Session-ID: 51F1D40A1B044700365D3BD1C61ABC745FB0C347A334E1410946DCB5EFE37AFD
Session-ID-ctx:
Master-Key: DF8194F6A60B073E049C87284856B5561476315145B55E35811028C4D97F77696F676DB019BB6E271E9965F289A99083
Key-Arg : None
Start Time: 1311801833
Timeout : 300 (sec)
Verify return code: 18 (self signed certificate)
---
As noted, after all that, it does connect successfully which is more than you can say for my Java app.
Should it be relevant, I'm using OS X 10.6.8, Java version 1.6.0_26.
The problem is the prime size. The maximum-acceptable size that Java accepts is 1024 bits. This is a known issue (see JDK-6521495).
The bug report that I linked to mentions a workaround using BouncyCastle's JCE implementation. Hopefully that should work for you.
UPDATE
This was reported as bug JDK-7044060 and fixed recently.
Note, however, that the limit was only raised to 2048 bit. For sizes > 2048 bit, there is JDK-8072452 - Remove the maximum prime size of DH Keys; the fix appears to be for 9.
The "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files" answer did not work for me but The BouncyCastle's JCE provider suggestion did.
Here are the steps I took using Java 1.6.0_65-b14-462 on Mac OSC 10.7.5
1) Download these jars:
bcprov-jdk15on-154.jar
bcprov-ext-jdk15on-154.jar
2) move these jars to $JAVA_HOME/lib/ext
3) edit $JAVA_HOME/lib/security/java.security as follows:
security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider
restart app using JRE and give it a try
Here is my solution (java 1.6), also would be interested why I had to do this:
I noticed from the javax.security.debug=ssl, that sometimes the used cipher suite is TLS_DHE_... and sometime it is TLS_ECDHE_.... The later would happen if I added BouncyCastle. If TLS_ECDHE_ was selected, MOST OF the time it worked, but not ALWAYS, so adding even BouncyCastle provider was unreliable (failed with same error, every other time or so). I guess somewhere in the Sun SSL implementation sometimes it choose DHE, sometimes it choose ECDHE.
So the solution posted here relies on removing TLS_DHE_ ciphers completely. NOTE: BouncyCastle is NOT required for the solution.
So create the server certification file by:
echo |openssl s_client -connect example.org:443 2>&1 |sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'
Save this as it will be referenced later, than here is the solution for an SSL http get, excluding the TLS_DHE_ cipher suites.
package org.example.security;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import org.apache.log4j.Logger;
public class SSLExcludeCipherConnectionHelper {
private Logger logger = Logger.getLogger(SSLExcludeCipherConnectionHelper.class);
private String[] exludedCipherSuites = {"_DHE_","_DH_"};
private String trustCert = null;
private TrustManagerFactory tmf;
public void setExludedCipherSuites(String[] exludedCipherSuites) {
this.exludedCipherSuites = exludedCipherSuites;
}
public SSLExcludeCipherConnectionHelper(String trustCert) {
super();
this.trustCert = trustCert;
//Security.addProvider(new BouncyCastleProvider());
try {
this.initTrustManager();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void initTrustManager() throws Exception {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(new FileInputStream(trustCert));
Certificate ca = null;
try {
ca = cf.generateCertificate(caInput);
logger.debug("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
KeyStore keyStore = KeyStore.getInstance("jks");
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
}
public String get(URL url) throws Exception {
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
SSLParameters params = context.getSupportedSSLParameters();
List<String> enabledCiphers = new ArrayList<String>();
for (String cipher : params.getCipherSuites()) {
boolean exclude = false;
if (exludedCipherSuites != null) {
for (int i=0; i<exludedCipherSuites.length && !exclude; i++) {
exclude = cipher.indexOf(exludedCipherSuites[i]) >= 0;
}
}
if (!exclude) {
enabledCiphers.add(cipher);
}
}
String[] cArray = new String[enabledCiphers.size()];
enabledCiphers.toArray(cArray);
// Tell the URLConnection to use a SocketFactory from our SSLContext
HttpsURLConnection urlConnection =
(HttpsURLConnection)url.openConnection();
SSLSocketFactory sf = context.getSocketFactory();
sf = new DOSSLSocketFactory(sf, cArray);
urlConnection.setSSLSocketFactory(sf);
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String inputLine;
StringBuffer buffer = new StringBuffer();
while ((inputLine = in.readLine()) != null)
buffer.append(inputLine);
in.close();
return buffer.toString();
}
private class DOSSLSocketFactory extends javax.net.ssl.SSLSocketFactory {
private SSLSocketFactory sf = null;
private String[] enabledCiphers = null;
private DOSSLSocketFactory(SSLSocketFactory sf, String[] enabledCiphers) {
super();
this.sf = sf;
this.enabledCiphers = enabledCiphers;
}
private Socket getSocketWithEnabledCiphers(Socket socket) {
if (enabledCiphers != null && socket != null && socket instanceof SSLSocket)
((SSLSocket)socket).setEnabledCipherSuites(enabledCiphers);
return socket;
}
#Override
public Socket createSocket(Socket s, String host, int port,
boolean autoClose) throws IOException {
return getSocketWithEnabledCiphers(sf.createSocket(s, host, port, autoClose));
}
#Override
public String[] getDefaultCipherSuites() {
return sf.getDefaultCipherSuites();
}
#Override
public String[] getSupportedCipherSuites() {
if (enabledCiphers == null)
return sf.getSupportedCipherSuites();
else
return enabledCiphers;
}
#Override
public Socket createSocket(String host, int port) throws IOException,
UnknownHostException {
return getSocketWithEnabledCiphers(sf.createSocket(host, port));
}
#Override
public Socket createSocket(InetAddress address, int port)
throws IOException {
return getSocketWithEnabledCiphers(sf.createSocket(address, port));
}
#Override
public Socket createSocket(String host, int port, InetAddress localAddress,
int localPort) throws IOException, UnknownHostException {
return getSocketWithEnabledCiphers(sf.createSocket(host, port, localAddress, localPort));
}
#Override
public Socket createSocket(InetAddress address, int port,
InetAddress localaddress, int localport) throws IOException {
return getSocketWithEnabledCiphers(sf.createSocket(address, port, localaddress, localport));
}
}
}
Finally here is how it is used (certFilePath if the path of the certificate saved from openssl):
try {
URL url = new URL("https://www.example.org?q=somedata");
SSLExcludeCipherConnectionHelper sslExclHelper = new SSLExcludeCipherConnectionHelper(certFilePath);
logger.debug(
sslExclHelper.get(url)
);
} catch (Exception ex) {
ex.printStackTrace();
}
The answer above is correct, but in terms of the workaround, I had problems with the BouncyCastle implementation when I set it as preferred provider:
java.lang.ArrayIndexOutOfBoundsException: 64
at com.sun.crypto.provider.TlsPrfGenerator.expand(DashoA13*..)
This is also discussed in one forum thread I found, which doesn't mention a solution.
http://www.javakb.com/Uwe/Forum.aspx/java-programmer/47512/TLS-problems
I found an alternative solution which works for my case, although I'm not at all happy with it. The solution is to set it so that the Diffie-Hellman algorithm is not available at all. Then, supposing the server supports an alternative algorithm, it will be selecting during normal negotiation. Obviously the downside of this is that if somebody somehow manages to find a server that only supports Diffie-Hellman at 1024 bits or less then this actually means it will not work where it used to work before.
Here is code which works given an SSLSocket (before you connect it):
List<String> limited = new LinkedList<String>();
for(String suite : ((SSLSocket)s).getEnabledCipherSuites())
{
if(!suite.contains("_DHE_"))
{
limited.add(suite);
}
}
((SSLSocket)s).setEnabledCipherSuites(limited.toArray(
new String[limited.size()]));
Nasty.
You can disable DHE completely in your jdk, edit jre/lib/security/java.security and make sure DHE is disabled, eg. like
jdk.tls.disabledAlgorithms=SSLv3, DHE.
You can installing the provider dynamically:
1) Download these jars:
bcprov-jdk15on-152.jar
bcprov-ext-jdk15on-152.jar
2) Copy jars to WEB-INF/lib (or your classpath)
3) Add provider dynamically:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
...
Security.addProvider(new BouncyCastleProvider());
This is a quite old post, but if you use Apache HTTPD, you can limit the DH size.
See http://httpd.apache.org/docs/current/ssl/ssl_faq.html#javadh
It is possible that you have incorrect Maven dependencies.
You must find these libraries in Maven dependency hierarchy:
bcprov-jdk14, bcpkix-jdk14, bcmail-jdk14
If you have these dependencies that is the error, and you should do this:
Add the dependency:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk15on</artifactId>
<version>1.59</version>
</dependency>
Exclude these dependencies from the artifact that included the wrong dependencies, in my case it is:
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>2.1.7</version>
<exclusions>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bctsp-jdk14</artifactId>
</exclusion>
<exclusion>
<groupId>bouncycastle</groupId>
<artifactId>bcprov-jdk14</artifactId>
</exclusion>
<exclusion>
<groupId>bouncycastle</groupId>
<artifactId>bcmail-jdk14</artifactId>
</exclusion>
</exclusions>
</dependency>
If you are using jdk1.7.0_04, upgrade to jdk1.7.0_21. The problem has been fixed in that update.
Try downloading "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files" from the Java download site and replacing the files in your JRE.
This worked for me and I didn't even need to use BouncyCastle - the standard Sun JCE was able to connect to the server.
PS. I got the same error (ArrayIndexOutOfBoundsException: 64) when I tried using BouncyCastle before changing the policy files, so it seems our situation is very similar.
If you are still bitten by this issue AND you are using Apache httpd v> 2.4.7, try this: http://httpd.apache.org/docs/current/ssl/ssl_faq.html#javadh
copied from the url:
Beginning with version 2.4.7, mod_ssl will use DH parameters which include primes with lengths of more than 1024 bits. Java 7 and earlier limit their support for DH prime sizes to a maximum of 1024 bits, however.
If your Java-based client aborts with exceptions such as java.lang.RuntimeException: Could not generate DH keypair and java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive), and httpd logs tlsv1 alert internal error (SSL alert number 80) (at LogLevel info or higher), you can either rearrange mod_ssl's cipher list with SSLCipherSuite (possibly in conjunction with SSLHonorCipherOrder), or you can use custom DH parameters with a 1024-bit prime, which will always have precedence over any of the built-in DH parameters.
To generate custom DH parameters, use the
openssl dhparam 1024
command. Alternatively, you can use the following standard 1024-bit DH parameters from RFC 2409, section 6.2:
-----BEGIN DH PARAMETERS-----
MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR
Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL
/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC
-----END DH PARAMETERS-----
Add the custom parameters including the "BEGIN DH PARAMETERS" and "END DH PARAMETERS" lines to the end of the first certificate file you have configured using the SSLCertificateFile directive.
I am using java 1.6 on client side, and it solved my issue. I didn't lowered the cipher suites or like, but added a custom generated DH param to the cert file..
I have the same problem with Yandex Maps server, JDK 1.6 and Apache HttpClient 4.2.1. The error was
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
with enabled debug by -Djavax.net.debug=all there was a message in a log
Could not generate DH keypair
I have fixed this problem by adding BouncyCastle library bcprov-jdk16-1.46.jar and registering a provider in a map service class
public class MapService {
static {
Security.addProvider(new BouncyCastleProvider());
}
public GeocodeResult geocode() {
}
}
A provider is registered at the first usage of MapService.
I encountered the SSL error on a CentOS server running JDK 6.
My plan was to install a higher JDK version (JDK 7) to co-exist with JDK 6 but it turns out that merely installing the newer JDK with rpm -i was not enough.
The JDK 7 installation would only succeed with the rpm -U upgrade option as illustrated below.
1. Download JDK 7
wget -O /root/jdk-7u79-linux-x64.rpm --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; o raclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.rpm"
2. RPM installation fails
rpm -ivh jdk-7u79-linux-x64.rpm
Preparing... ########################################### [100%]
file /etc/init.d/jexec from install of jdk-2000:1.7.0_79-fcs.x86_64 conflicts with file from package jdk-2000:1.6.0_43-fcs.x86_64
3. RPM upgrade succeeds
rpm -Uvh jdk-7u79-linux-x64.rpm
Preparing... ########################################### [100%]
1:jdk ########################################### [100%]
Unpacking JAR files...
rt.jar...
jsse.jar...
charsets.jar...
tools.jar...
localedata.jar...
jfxrt.jar...
4. Confirm the new version
java -version
java version "1.7.0_79"
Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)
Solved the problem by upgrading to JDK 8.
I use coldfusion 8 on JDK 1.6.45 and had problems with <cfdocument ...> giving me just red crosses instead of images, and also with cfhttp not able to connect to the local webserver with ssl.
my test script to reproduce with coldfusion 8 was
<CFHTTP URL="https://www.onlineumfragen.com" METHOD="get" ></CFHTTP>
<CFDUMP VAR="#CFHTTP#">
this gave me the quite generic error of " I/O Exception: peer not authenticated."
I then tried to add certificates of the server including root and intermediate certificates to the java keystore and also the coldfusion keystore, but nothing helped.
then I debugged the problem with
java SSLPoke www.onlineumfragen.com 443
and got
javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair
and
Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be
multiple of 64, and can only range from 512 to 1024 (inclusive)
at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DashoA13*..)
at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:627)
at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:107)
... 10 more
I then had the idea that the webserver (apache in my case) had very modern ciphers for ssl and is quite restrictive (qualys score a+) and uses strong Diffie-hellman groups with more than 1024 bits. Obviously, ColdFusion and Java JDK 1.6.45 can not manage this.
Next step in the odyssey was to think of installing an alternative security provider for java, and I decided for bouncy castle.
see also http://www.itcsolutions.eu/2011/08/22/how-to-use-bouncy-castle-cryptographic-api-in-netbeans-or-eclipse-for-java-jse-projects/
I then downloaded the
bcprov-ext-jdk15on-156.jar
from http://www.bouncycastle.org/latest_releases.html and installed it under
C:\jdk6_45\jre\lib\ext or where ever your jdk is, in original install of coldfusion 8 it would be under C:\JRun4\jre\lib\ext but I use a newer jdk (1.6.45) located outside the coldfusion directory. it is very important to put the bcprov-ext-jdk15on-156.jar in the \ext directory (this cost me about two hours and some hair ;-)
then I edited the file C:\jdk6_45\jre\lib\security\java.security (with wordpad not with editor.exe!) and put in one line for the new provider. afterwards the list looked like
#
# List of providers and their preference orders (see above):
#
security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider
security.provider.2=sun.security.provider.Sun
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
security.provider.10=sun.security.mscapi.SunMSCAPI
(see the new one in position 1)
then restart coldfusion service completely.
you can then
java SSLPoke www.onlineumfragen.com 443 (or of course your url!)
and enjoy the feeling...
and of course
<cfhttp and <cfdocument worked like a charm and like before we "hardened" our ssl ciphers in apache!
what a night and what a day. Hopefully this will help (partially or fully) to someone out there. if you have questions, just mail me at info ... (domain above).
We got the same exact exception error returned, to fix it was easy after hours surfing the internet.
We downloaded the highest version of jdk we could find on oracle.com, installed it and pointed Jboss application server to the directory of the installed new jdk.
Restarted Jboss, reprocessed, problemo fixed!!!
I've got this error with Bamboo 5.7 + Gradle project + Apache. Gradle tried to get some dependencies from one of our servers via SSL.
Solution:
Generate DH Param:
with OpenSSL:
openssl dhparam 1024
example output:
-----BEGIN DH PARAMETERS-----
MIGHfoGBALxpfMrDpImEuPlhopxYX4L2CFqQov+FomjKyHJrzj/EkTP0T3oAkjnS
oCGh6p07kwSLS8WCtYJn1GzItiZ05LoAzPs7T3ST2dWrEYFg/dldt+arifj6oWo+
vctDyDqIjlevUE+vyR9MF6B+Rfm4Zs8VGkxmsgXuz0gp/9lmftY7AgEC
-----END DH PARAMETERS-----
Append output to certificate file (for Apache - SSLCertificateFile param)
Restart apache
Restart Bamboo
Try to build project again
I used to get a similar error accessing svn.apache.org with java SVN clients using an IBM JDK. Currently, svn.apache.org users the clients cipher preferences.
After running just once with a packet capture / javax.net.debug=ALL I was able to blacklist just a single DHE cipher and things work for me (ECDHE is negotiated instead).
.../java/jre/lib/security/java.security:
jdk.tls.disabledAlgorithms=SSL_DHE_RSA_WITH_AES_256_CBC_SHA
A nice quick fix when it is not easy to change the client.
Recently I have the same issue and after upgrading jdk version from 1.6.0_45 to jdk1.7.0_191 which resolved the issue.
Window -> Preferences -> Java -> Installed JREs ->select the jre and Edit. And in the Default VM Arguments enter
-Dcom.sun.net.ssl.enableECC=false
Click Finish
If the server supports a cipher that does not include DH, you can force the client to select that cipher and avoid the DH error. Such as:
String pickedCipher[] ={"TLS_RSA_WITH_AES_256_CBC_SHA"};
sslsocket.setEnabledCipherSuites(pickedCipher);
Keep in mind that specifying an exact cipher is prone to breakage in the long run.
For me, the following command line fixed the issue:
java -jar -Dhttps.protocols=TLSv1.2 -Ddeployment.security.TLSv1.2=true
-Djavax.net.debug=ssl:handshake XXXXX.jar
I am using JDK 1.7.0_79

JMeter: "javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake" while recording in JMeter [duplicate]

I am getting javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake exception when I try to do HTTPS Post of a web service through internet. But same code works for other internet hosted web services. I tried many things, nothing is helping me. I posted my sample code here. Can anyone please help me to resolve this problem?
public static void main(String[] args) throws Exception {
String xmlServerURL = "https://example.com/soap/WsRouter";
URL urlXMLServer = new URL(xmlServerURL);
// URLConnection supports HTTPS protocol only with JDK 1.4+
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
"xxxx.example.com", 8083));
HttpURLConnection httpsURLConnection = (HttpURLConnection) urlXMLServer
.openConnection(proxy);
httpsURLConnection.setRequestProperty("Content-Type","text/xml; charset=utf-8");
//httpsURLConnection.setDoInput(true);
httpsURLConnection.setDoOutput(true);
httpsURLConnection.setConnectTimeout(300000);
//httpsURLConnection.setIgnoreProxy(false);
httpsURLConnection.setRequestMethod("POST");
//httpsURLConnection.setHostnameVerifier(DO_NOT_VERIFY);
// send request
PrintWriter out = new PrintWriter(
httpsURLConnection.getOutputStream());
StringBuffer requestXML = new StringBuffer();
requestXML.append(getProcessWorkOrderSOAPXML());
// get list of user
out.println(requestXML.toString());
out.close();
out.flush();
System.out.println("XML Request POSTed to " + xmlServerURL + "\n");
System.out.println(requestXML.toString() + "\n");
//Thread.sleep(60000);
// read response
BufferedReader in = new BufferedReader(new InputStreamReader(
httpsURLConnection.getInputStream()));
String line;
String respXML = "";
while ((line = in.readLine()) != null) {
respXML += line;
}
in.close();
// output response
respXML = URLDecoder.decode(respXML, "UTF-8");
System.out.println("\nXML Response\n");
System.out.println(respXML);
}
Full stacktrace:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:946)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1091)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
at com.labcorp.efone.vendor.TestATTConnectivity.main(TestATTConnectivity.java:43)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:482)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
... 8 more
Actually, there are two scenarios here. When I work as a standalone Java program I am getting the above exception. But when I try to execute in weblogic application server, I am getting the below exception: Any clue what could be the reason?
java.io.IOException: Connection closed, EOF detected
at weblogic.socket.JSSEFilterImpl.handleUnwrapResults(JSSEFilterImpl.java:637)
at weblogic.socket.JSSEFilterImpl.unwrapAndHandleResults(JSSEFilterImpl.java:515)
at weblogic.socket.JSSEFilterImpl.doHandshake(JSSEFilterImpl.java:96)
at weblogic.socket.JSSEFilterImpl.doHandshake(JSSEFilterImpl.java:75)
at weblogic.socket.JSSEFilterImpl.write(JSSEFilterImpl.java:448)
at weblogic.socket.JSSESocket$JSSEOutputStream.write(JSSESocket.java:93)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at java.io.FilterOutputStream.flush(FilterOutputStream.java:140)
at weblogic.net.http.HttpURLConnection.writeRequests(HttpURLConnection.java:192)
at weblogic.net.http.HttpURLConnection.getInputStream(HttpURLConnection.java:433)
at weblogic.net.http.SOAPHttpsURLConnection.getInputStream(SOAPHttpsURLConnection.java:37)
at com.labcorp.efone.service.impl.WorkOrderServiceImpl.processATTWorkOrder(ATTWorkOrderServiceImpl.java:86)
at com.labcorp.efone.bds.WorkOrderBusinessDelegateImpl.processATTWorkOrder(WorkOrderBusinessDelegateImpl.java:59)
at com.labcorp.efone.actions.ATTWorkOrderAction.efonePerformForward(ATTWorkOrderAction.java:41)
at com.labcorp.efone.actions.EfoneAction.efonePerformActionForward(EfoneAction.java:149)
at com.labcorp.efone.actions.EfoneAction.execute(EfoneAction.java:225)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:751)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:844)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:280)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:254)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:136)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:341)
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:25)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at com.labcorp.efone.security.EfoneAuthenticationFilter.doFilter(EfoneAuthenticationFilter.java:115)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3367)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3333)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:57)
at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2220)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2146)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2124)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1564)
at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:254)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:295)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:254)
Exception: java.io.IOException: Connection closed, EOF detected
Java 7 defaults to TLS 1.0, which can cause this error when that protocol is not accepted. I ran into this problem with a Tomcat application and a server that would not accept TLS 1.0 connections any longer. I added
-Dhttps.protocols=TLSv1.1,TLSv1.2
to the Java options and that fixed it. (Tomcat was running Java 7.)
I faced the same problem and solved it by adding:
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
before openConnection method.
Not an answer yet, but too much for a comment. This is clearly not a server cert problem; the symptoms of that are quite different. From your system's POV, the server appears to be closing during the handshake. There are two possibilities:
The server really is closing, which is a SSL/TLS protocol violation though a fairly minor one; there are quite a few reasons a server might fail to handshake with you but it should send a fatal alert first, which your JSSE or the weblogic equivalent should indicate. In this case there may well be some useful information in the server log, if you are able (and permitted) to communicate with knowledgeable server admin(s). Or you can try putting a network monitor on your client machine, or one close enough it sees all your traffic; personally I like www.wireshark.org. But this usually shows only that the close came immediately after the ClientHello, which doesn't narrow it down much. You don't say if you are supposed to and have configured a "client cert" (actually key&cert, in the form of a Java privateKeyEntry) for this server; if that is required by the server and not correct, some servers may perceive that as an attack and knowingly violate protocol by closing even though officially they should send an alert.
Or, some middlebox in the network, most often a firewall or purportedly-transparent proxy, is deciding it doesn't like your connection and forcing a close. The Proxy you use is an obvious suspect; when you say the "same code" works to other hosts, confirm if you mean through the same proxy (not just a proxy) and using HTTPS (not clear HTTP). If that isn't so, try testing to other hosts with HTTPS through the proxy (you needn't send a full SOAP request, just a GET / if enough). If you can, try connecting without the proxy, or possibly a different proxy, and connecting HTTP (not S) through the proxy to the host (if both support clear) and see if those work.
If you don't mind publishing the actual host (but definitely not any authentication credentials) others can try it. Or you can go to www.ssllabs.com and request they test the server (without publishing the results); this will try several common variations on SSL/TLS connection and report any errors it sees, as well as any security weaknesses.
A first step to diagnose the issue is by starting the client - and if you are running the server yourself, a private test instance of the server - by starting Java with the VM option:
-Djavax.net.debug=all
See also https://blogs.oracle.com/java-platform-group/entry/diagnosing_tls_ssl_and_https
I encountered a similar problem with glassfish application server and Oracle JDK/JRE but not in Open JDK/JRE.
When connecting to a SSL domain I always ran into:
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
...
Caused by: java.io.EOFException: SSL peer shut down incorrectly
The solution for me was to install the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files because the server only understood certificates that are not included in Oracle JDK by default, only OpenJDK includes them.
After installing everything worked like charme.
JCE 7: http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
JCE 8: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
I think you are missing your certificates.
You can try generating them by using InstallCerts app. Here you can see how to use it:
https://github.com/escline/InstallCert
Once you get your certificate, you need to put it under your security directory within your jdk home, for example:
C:\Program Files\Java\jdk1.6.0_45\jre\lib\security
Let me know if it works.
I ran into a similar issue and found I was hitting the wrong port. After fixing the port things worked great.
In my case, I got this problem because I had given the server a non-existent certificate, due to a typo in the config file. Instead of throwing an exception, the server proceeded like normal and sent an empty certificate to the client. So it might be worth checking to make sure that the server is providing the correct response.
I experienced this error while using the Jersey Client to connect to a server. The way I resolved it was by debugging the library and seeing that it actually did receive an EOF the moment it tried to read. I also tried connecting using a web browser and got the same results.
Just writing this here in case it ends up helping anyone.
You May Write this below code insdie your current java programme
System.setProperty("https.protocols", "TLSv1.1");
or
System.setProperty("http.proxyHost", "proxy.com");
System.setProperty("http.proxyPort", "911");
Thanks to all for sharing your answers and examples. The same standalone program worked for me by small changes and adding the lines of code below.
In this case, keystore file was given by webservice provider.
// Small changes during connection initiation..
// Please add this static block
static {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
{ #Override
public boolean verify(String hostname, SSLSession arg1) {
// TODO Auto-generated method stub
if (hostname.equals("X.X.X.X")) {
System.out.println("Return TRUE"+hostname);
return true;
}
System.out.println("Return FALSE");
return false;
}
});
}
String xmlServerURL = "https://X.X.X.X:8080/services/EndpointPort";
URL urlXMLServer = new URL(null,xmlServerURL,new sun.net.www.protocol.https.Handler());
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) urlXMLServer .openConnection();
// Below extra lines are added to the same program
//Keystore file
System.setProperty("javax.net.ssl.keyStore", "Drive:/FullPath/keystorefile.store");
System.setProperty("javax.net.ssl.keyStorePassword", "Password"); // Password given by vendor
//TrustStore file
System.setProperty("javax.net.ssl.trustStore"Drive:/FullPath/keystorefile.store");
System.setProperty("javax.net.ssl.trustStorePassword", "Password");
I encountered this problem with Java 1.6. Running under Java 1.7 fixed my particular rendition of the problem. I think the underlying cause was that the server I was connecting to must have required stronger encryption than was available under 1.6.
I had the same error, but in my case it was caused by the DEBUG mode in Intellij IDE. The debug slowed down the library and then server ended communication at handshake phase. The standard "RUN" worked perfectly.
I run my application with Java 8 and Java 8 brought security certificate onto its trust store. Then I switched to Java 7 and added the following into VM options:
-Djavax.net.ssl.trustStore=C:\<....>\java8\jre\lib\security\cacerts
Simply I pointed to the location where a certificate is.
I was using the p12 which I exported with Keychain in my MacBook, however, it didn't work on my java-apns server code. What I had to do was to create a new p12 key as stated here, using my already generated pem keys:
openssl pkcs12 -export -in your_app.pem -inkey your_key.pem -out your_app_key.p12
Then updated the path to that new p12 file and everything worked perfectly.
How you would solve it is by going to
Settings
Search"Network"
Choose "Use IDEA general proxy settings as default Subversion"
As per https://kb.informatica.com/solution/23/Pages/69/570664.aspx adding this property works
CryptoProtocolVersion=TLSv1.2
With base at TLSv1.2 ALERT: fatal, handshake_failure I obtained after debug with this thread previos answer
-Djavax.net.debug=all
I went to https://www.ssllabs.com/and observed that the web server required a SSLv3 connection deprecate at june 2015, and deprecated at JDKu31 Release notes
I edited the ${java_home}/jre/lib/security/java.security at the line
jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024,
EC keySize < 224, 3DES_EDE_CBC, anon, NULL
to
jdk.tls.disabledAlgorithms= RC4, DES, MD5withRSA, DH keySize < 1024,
EC keySize < 224, 3DES_EDE_CBC, anon, NULL
As a final step I got this error
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target [javax.net.ssl.SSLHandshakeException]
I fixed this intalling the cert with the java keytool, following this answer PKIX path building failed” and “unable to find valid certification path to requested target”
I get this error when specifying a https url and in the same url explicitly specifying an http port (instead of an https port). Removing the explicit port :8080 solved the issue for me.
Adding certificates to Java\jdk\jre\lib\security folder worked for me. If you are using Chrome click on the green bulb [https://support.google.com/chrome/answer/95617?p=ui_security_indicator&rd=1] and save the certificate in security folder.
I faced the same issue once. I think its because of the URL
String xmlServerURL = "https://example.com/soap/WsRouter";
Check whether its a proper one or not ??
javax.net.ssl.SSLHandshakeException is because the server not able to connect to the specified URL because of following reason-
Either the identity of the website is not verified.
Server's certificate does not match the URL.
Or, Server's certificate is not trusted.
This is what solve my problem.
If you are trying to use debugger make sure you breakpoint is not on URL or URLConnection just put your breakpoint on BufferReader or inside while loop.
If nothing works try using apache library http://hc.apache.org/index.html.
no SSL, no JDK update needed, no need to set properties even, just simple trick :)

Apache http core nio 4.3.3 reverse proxy SSL error

I am developing a reverse proxy using http core nio 4.3.3 and need to connect to a Secure/HTTPS endpoint via the proxy. I took the reverse proxy(Asynchronous HTTP reverse proxy)[1] and added SSL support as shown below.
SSLContext clientSSLContext =
SSLUtil.createClientSSLContext(TRUST_STORE_LOCATION,
TRUST_STORE_PASSWORD);
final IOEventDispatch connectingEventDispatch =
new DefaultHttpClientIODispatch(
clientHandler,
clientSSLContext,
ConnectionConfig.DEFAULT);
...
connectingIOReactor.execute(connectingEventDispatch);
When I send the request, I am getting this error,
java.io.IOException: SSL not supported
The Stack trace is given below.
[client<-proxy] 00000001 java.io.IOException: SSL not supported
java.io.IOException: SSL not supported
at org.apache.http.impl.nio.pool.BasicNIOConnFactory.create(BasicNIOConnFactory.java:159)
at org.apache.http.impl.nio.pool.BasicNIOConnFactory.create(BasicNIOConnFactory.java:1)
at org.apache.http.nio.pool.AbstractNIOConnPool.requestCompleted(AbstractNIOConnPool.java:484)
at org.apache.http.nio.pool.AbstractNIOConnPool$InternalSessionRequestCallback.completed(AbstractNIOConnPool.java:770)
at org.apache.http.impl.nio.reactor.SessionRequestImpl.completed(SessionRequestImpl.java:127)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processNewChannels(AbstractIOReactor.java:423)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:288)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:105)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:586)
at java.lang.Thread.run(Thread.java:662)
I enabled SSL debug logs as well, but still could not figure out the issue.
Then I debugged this and found out that the proxy received the request from the client and drops due to an exception inside the handle method of HttpAsyncRequestConsumer. The exception is java.io.IOException: SSL not supported
Also note that the SSLContext was working fine with a reverse proxy written using the netty transport.
Any help would be appreciated.
[1] https://hc.apache.org/httpcomponents-core-ga/examples.html
Regards,
Ravindra.
When using a connection pool on the client side to manage outgoing connections one needs to ensure that the connection factory used by the pool to create new connection objects is SSL capable. Please make sure that the connection pool is properly configured.
Thanks a lot for the advice. That solved the issue.
clientSSLContext =
SSLUtil.createClientSSLContext(TRUST_STORE_LOCATION,
TRUST_STORE_PASSWORD);
BasicNIOConnFactory connectionFactory =
new BasicNIOConnFactory(
clientSSLContext,
null,
ConnectionConfig.DEFAULT);
proxyConnPool = new ProxyConnPool(connectingIOReactor, connectionFactory, 5000)

Connecting to a Websphere MQ in Java with SSL/Keystore

I'd like to connect to a Websphere 6.0 MQ via Java. I have already working code for a "normal" queue, but now I need to access a new queue which is SSL encrypted (keystore). I have been sent a file called something.jks, which I assume is a certificate I need to store somewhere. I have been searching the net, but I can't find the right information.
This is the code I use for the "normal" queue. I assume I need to set some property, but not sure which one.
MQQueueConnectionFactory connectionFactory = new MQQueueConnectionFactory();
connectionFactory.setChannel(channel_);
connectionFactory.setHostName(hostname_);
connectionFactory.setPort(port_);
connectionFactory.setQueueManager(queueManager_);
connectionFactory.setTransportType(1);
connectionFactory.setSSsetSSLCertStores(arg0)
Connection connection = connectionFactory.createConnection();
connection.setExceptionListener(this);
session_ = connection.createSession(DEFAULT_TRANSACTED, DEFAULT_ACKMODE);
connection.start();
javax.jms.Queue fQueue = session_.createQueue(queue_);
consumer = session_.createConsumer(fQueue);
Alex Fehners tutorial in developerWorks is a bit old (2005) but has code samples that should work for you.
SSL configuration of the Websphere MQ Java/JMS client
Your Java app will authenticate the QMgr based on its certificate. That means the jks file you were provided must have either the QMgr's self-signed certificate or it will have the root certificate of a Certificate Authority that signed the QMgr's certificate. In either case you point to the file using the -Djavax.net.ssl.trustStore=<location of trustStore> as noted in the article linked above. If the jks has a password, you will need to specify -Djavax.net.ssl.trustStorePassword=<password> as well. Authenticating the QMgr with a truststore is always required. The next part may or may not be required.
The other piece of the puzzle is that the QMgr may require your app to present a certificate. In other words, the QMgr cert is always authenticated, whether the app is required to authenticate is optional. If it is then you have what is known as "mutual authentication". If the channel that you connect to has been configured with SSLCAUTH(REQUIRED) then mutual auth has been enabled and the QMgr must have your application's self-signed cert or a CA root cert that signed your app's cert in its keystore. Hopefully whoever set up your jks file will have arranged for this already.
Assuming mutual auth is required, then your jks will have, in addition to the QMgr's trusted cert, a private cert representing your application. To get the app to fetch the cert and present it to the QMgr, you use the -Djavax.net.ssl.keyStore=<location of keyStore> and -Djavax.net.ssl.keyStorePassword=<password> parameters. Note these say key store whereas the previous parms said trust store.
My recommendation is to work with the WMQ administrator to set up and test the SSL connection. The first phase should be to test the channel with SSLCAUTH(OPTIONAL). This verifies that the application can resolve and authenticate the QMgr's certificate. Only when you get this working would the WMQ admin then change the channel to SSLCAUTH(REQUIRED) which tests authentication in the reverse direction.
I would highly recommend that you use the WMQ v7 client for a new application. This is for two reasons: 1) v6 is end-of-life as of Sept 2011; 2) the v7 code has a lot more diagnostic capability built in. The v7 client code is completely compatible with a v6 QMgr and works like the v6 client. You just don't get the v7 functionality. Download the WMQ client code free here:
IBM - MQC7: WebSphere MQ V7.0 Clients
I'm running the WMQ Hands-On Security Lab at IMPACT this year and will be posting the scripts and lab guide over the weekend at http://t-rob.net so check back for that.
Using SSL from the Oracle JVM (JSSE)
See also "What TLS cipherspecs/ciphersuites are supported when connecting from Oracle Java (non-IBM JRE) to MQ queue manager?"
In MQ Client version 8.0.0.2 there is a patch is included to use the TLS with Oracle JVM, this works with lanes answer above
The get this to work you will need the latest MQ Client that contains
IV66840: WMQ V7 JAVA/JMS: ADD SUPPORT FOR SELECTED TLS CIPHERSPECS WHEN
RUNNING IN NON-IBM JAVA RUNTIME ENVIRONMENT
http://www-01.ibm.com/support/docview.wss?uid=swg1IV66840
(download)
Depending on your location you may also need to install
Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 8 (download)
To use this you have to configured by using the JVM argument:
-Dcom.ibm.mq.cfg.useIBMCipherMappings=false
Note that the default security implementation behaviour differs between Oracle and IBM JVMs :
The Oracle JSSE Reference guide says:
If the KeyManager[] parameter is null, then an empty KeyManager will
be defined for this context.
The IBM JSSE Reference guide says:
If the KeyManager[] paramater is null, the installed security
providers will be searched for the highest-priority implementation of
the KeyManagerFactory, from which an appropriate KeyManager will be
obtained.
Which means that you have to setup your own ssl context
SSLContext sslcontext = SSLContext.getInstance("TLS");
String keyStore = System.getProperty("javax.net.ssl.keyStore");
String keyStoreType = System.getProperty("javax.net.ssl.keyStoreType", KeyStore.getDefaultType());
String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword","");
KeyManager[] kms = null;
if (keyStore != null)
{
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance(keyStoreType);
if (keyStore != null && !keyStore.equals("NONE")) {
fs = new FileInputStream(keyStore);
ks.load(fs, keyStorePassword.toCharArray());
if (fs != null)
fs.close();
char[] password = null;
if (keyStorePassword.length() > 0)
password = keyStorePassword.toCharArray();
kmf.init(ks,password);
kms = kmf.getKeyManagers();
}
sslcontext.init(kms,null,null);
And then supply that to the MQ JMS client:
JmsConnectionFactory cf = ...
MQConnectionFactory mqcf = (MQConnectionFactory) cf;
mqcf.setSSLSocketFactory(sslcontext.getSocketFactory());
If using a application server this might be handled by your application server.
Try this code along with T.Robs explanations about the certificate:
import com.ibm.mq.jms.*;
import java.io.FileInputStream;
import java.io.Console;
import java.security.*;
import javax.jms.JMSException;
import javax.jms.QueueConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import com.ibm.mq.jms.MQQueueConnectionFactory;
public class SSLTest {
public static void main(String[] args) {
System.out.println(System.getProperty("java.home"));
String HOSTNAME = "myhost";
String QMGRNAME = "MyQMGR";
String CHANNEL = "MY.SVRCONN";
String SSLCIPHERSUITE = "TLS_RSA_WITH_AES_256_CBC_SHA";
try {
Class.forName("com.sun.net.ssl.internal.ssl.Provider");
System.out.println("JSSE is installed correctly!");
Console console = System.console();
char[] KSPW = console.readPassword("Enter keystore password: ");
// instantiate a KeyStore with type JKS
KeyStore ks = KeyStore.getInstance("JKS");
// load the contents of the KeyStore
ks.load(new FileInputStream("/home/hudo/hugo.jks"), KSPW);
System.out.println("Number of keys on JKS: "
+ Integer.toString(ks.size()));
// Create a keystore object for the truststore
KeyStore trustStore = KeyStore.getInstance("JKS");
// Open our file and read the truststore (no password)
trustStore.load(new FileInputStream("/home/xwgztu2/xwgztu2.jks"), null);
// Create a default trust and key manager
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyManagerFactory keyManagerFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
// Initialise the managers
trustManagerFactory.init(trustStore);
keyManagerFactory.init(ks,KSPW);
// Get an SSL context.
// Note: not all providers support all CipherSuites. But the
// "SSL_RSA_WITH_3DES_EDE_CBC_SHA" CipherSuite is supported on both SunJSSE
// and IBMJSSE2 providers
// Accessing available algorithm/protocol in the SunJSSE provider
// see http://java.sun.com/javase/6/docs/technotes/guides/security/SunProviders.html
SSLContext sslContext = SSLContext.getInstance("SSLv3");
// Acessing available algorithm/protocol in the IBMJSSE2 provider
// see http://www.ibm.com/developerworks/java/jdk/security/142/secguides/jsse2docs/JSSE2RefGuide.html
// SSLContext sslContext = SSLContext.getInstance("SSL_TLS");
System.out.println("SSLContext provider: " +
sslContext.getProvider().toString());
// Initialise our SSL context from the key/trust managers
sslContext.init(keyManagerFactory.getKeyManagers(),
trustManagerFactory.getTrustManagers(), null);
// Get an SSLSocketFactory to pass to WMQ
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
// Create default MQ connection factory
MQQueueConnectionFactory factory = new MQQueueConnectionFactory();
// Customize the factory
factory.setSSLSocketFactory(sslSocketFactory);
// Use javac SSLTest.java -Xlint:deprecation
factory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
factory.setQueueManager(QMGRNAME);
factory.setHostName(HOSTNAME);
factory.setChannel(CHANNEL);
factory.setPort(1414);
factory.setSSLFipsRequired(false);
factory.setSSLCipherSuite(SSLCIPHERSUITE);
QueueConnection connection = null;
connection = factory.createQueueConnection("",""); //empty user, pass to avoid MQJMS2013 messages
connection.start();
System.out.println("JMS SSL client connection started!");
connection.close();
} catch (JMSException ex) {
ex.printStackTrace();
} catch (Exception ex){
ex.printStackTrace();
}
}
}
Be aware of which JRE you are using. We have had big trouble in using Sun JDK, because of a certain cryptation (TLS_RSA_WITH_AES_128_CBC_SHA) on the SSL channel to the IBM MQ. We used a X509 certeficate. In order to get it working we are using IBM JRE because it has much bigger support for certain cipher suites!