I have a Java application that will need to connect to a SSL
server.
That server provides a proprietary certificate that is not automatically recognized by the Java cacert
.
so I have 2 solutions:
a) import manually the certificate (.der, .pem etc.) in my client's java
local keystore
b) implement a trust manager that trusts all certificates
based on:
// prepare Verifiers that will accept certificate from ANY host
yesHostnameVerifier = new CYesHostnameVerifier();
// initiate the SSL context and prepare trust manager that will accept ANY certificate
TrustManager yesTrustManager = new CYesTrustManager();
TrustManager[] yesTrustManagers = new TrustManager[] {yesTrustManager};
try {
SSLContext yesSslcontext = SSLContext.getInstance("TLS");
yesSslcontext.init(null, yesTrustManagers, null); // key manager, trust manager, secure random manager
yesSslFactory = yesSslcontext.getSocketFactory();
} catch (Exception e) {
}
// configure the HTTPS connection
HttpsURLConnection.setDefaultSSLSocketFactory(yesSslFactory);
HttpsURLConnection.setDefaultHostnameVerifier(yesHostnameVerifier);
and
public class CYesTrustManager implements X509TrustManager {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
}
and
public class CYesHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
}
In my opinion:
- a) is impossible because I can't oblige all the clients to manually do that
- b) is totally unsecure in production contexts and prone to man-in-the-midle attacks so, I don't want to accept ALL certificates.
Instead, what I would like is to do all this programmatically:
When an exception is thrown because of invalid certificate:
1) get the server certificate from the SSL session
2) get the main useful information from this certificate and show this to the user (thru Swing)
3) ask the user if he accepts this certificate
4) if yes, import the certificate in the local keystore
All this programmatically.
This way, if one day the certificate is tampered at least a new message will be displayed to the user hence making it a bit suspect. This would work pretty similarly to a standard ssh session at the end. Good idea? bad idea?
Would someone have some sample code for 1) 2) and 4)