I have an application which connects to SAP systems via SSL. The application makes use of JAX-WS (for Web-Service calls) and Apache HttPComponent 4.5.3 for all other SSL calls. Everything works fine unless I run the application with Java 1.8 131 or 144. I'm getting the following exception:
javax.net.ssl.SSLHandshakeException:
java.security.cert.CertificateException: Certificates does not conform
to algorithm constraints at sun.security.ssl.Alerts.getSSLException(Unknown Source) at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source) at sun.security.ssl.Handshaker.fatalSE(Unknown Source) at sun.security.ssl.Handshaker.fatalSE(Unknown Source) at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source) at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source) at sun.security.ssl.Handshaker.processLoop(Unknown Source) at sun.security.ssl.Handshaker.process_record(Unknown Source) at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source) at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) Caused by: java.security.cert.CertificateException: Certificates does not conform to algorithm constraints at
security.ssl.AbstractTrustManagerWrapper.checkAlgorithmConstraints(Unknow at
security.ssl.AbstractTrustManagerWrapper.checkAdditionalTrust(Unknown at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(Unknown
I have read java.security.cert.CertificateException: Certificates does not conform to algorithm constraints but it doesn't apply to my case, because...
- Everything works fine when I connect to SAP server 1
- When connecting to SAP Server 2 afterwards (also via SSL) I get "certificate does not conform" error
- When I reverse the sequence and connect to SAP Server 2 first, everything works fine
- but then I get the same error when I connect to SAP server 1 (which worked before)
- And this problem only occurs with Java 1.8 131 and 144. It works fine with 1.7 and Java 1.8.121
All this indicates to me that the root cause is not a problem with the certificates and ciphers but something is going wrong when mixing JAX-WS and Apache HTTPS calls in Java 1.8.144
This is code for disabling SSL checks for JAX-WS (based on https://log.rowanto.com/java-8-turning-off-ssl-certificate-check/):
public static final void disableCertificateValidationForWebServices() {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {
new X509ExtendedTrustManager() {
@Override
public void checkClientTrusted(X509Certificate[]
x509Certificates, String s) { }
@Override
public void checkServerTrusted(X509Certificate[]
x509Certificates, String s) { }
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[]
x509Certificates, String s, Socket socket) {
}
@Override
public void checkServerTrusted(X509Certificate[]
x509Certificates, String s, Socket socket) {
}
@Override
public void checkClientTrusted(X509Certificate[]
x509Certificates, String s, SSLEngine sslEngine) {
}
@Override
public void checkServerTrusted(X509Certificate[]
x509Certificates, String s, SSLEngine sslEngine) {
}
} };
// Install the all-trusting trust manager
try {
final SSLContext sc = SSLContext.getInstance("SSL"); // or TLS?
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
.setDefaultHostnameVerifier(NoopHostnameVerifier.INSTANCE); } catch (Exception e) {
}
}
and this is the code for disabling SSL checks for the Apache HTTPS calls (based on http://stackoverflow.com/questions/22606579/apache-httpclient-4-3-and-x509-client-certificate-to-authenticate):
public static SSLConnectionSocketFactory getInstance() {
if (instance == null) {
Log.info("Disabling SSL Certificate Checks");
final SSLContextBuilder builder = SSLContexts.custom();
// here in the loadTrustMaterial the SSL Provider is loaded.
try {
builder.loadTrustMaterial(null, new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] arg0, String
arg1) {
return true;
}
});
final SSLContext sslContext = builder.build();
instance = new SSLConnectionSocketFactory(sslContext,
NoopHostnameVerifier.INSTANCE);
} catch (NoSuchAlgorithmException e) {
Log.error("disableCertificateValidation() failed with
NoSuchAlgorithmException. Detail message:", e);
listTrustManagers(null);
} catch (KeyStoreException e) {
Log.error("disableCertificateValidation() failed with
KeyStoreException. Detail message: ", e);
listTrustManagers(null);
} catch (KeyManagementException e) {
Log.error("disableCertificateValidation() failed with
KeyManagementException. Detail message: ", e);
}
}
return instance;
}
And yes, we are using a PoolingConnectionManager:
public final class MyPoolingHttpClientConnectionManager {
private static PoolingHttpClientConnectionManager instance = null;
private final static Object LOCK = new Object();
protected MyPoolingHttpClientConnectionManager() {
// Exists only to defeat instantiation.
}
public static PoolingHttpClientConnectionManager getInstance() {
synchronized (LOCK) {
if (instance == null) {
instance = new
PoolingHttpClientConnectionManager(disableCertificateValidation());
// Increase max total connection to 50
instance.setMaxTotal(50);
// Increase default max connection per route to 20
instance.setDefaultMaxPerRoute(20);
}
}
return instance;
}
/*
* This is called when we create the HTTPConnectionPool
*
*
*/
private final static Registry<ConnectionSocketFactory>
disableCertificateValidation() {
return RegistryBuilder.<ConnectionSocketFactory>
create().register("https", MySSLContext.getInstance())
.register("http", new
PlainConnectionSocketFactory()).build();
}
}
Any ideas are highly welcome