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:
<
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>
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 use coldfusion 8 on JDK 1.6.45 and had problems with 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 hellmann keys with more than 1024 bits. obviously, coldfusion and java jdk 1.6.45 can not manage this. Next step in the odysee 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
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).
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.
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();
}
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:
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