How to make self-signed certificate code execute only once? - java

Setup:
I am using Spring-MVC in one of my project. I have to access a URL for which I have to use self-signed certificates. I am using the following code in my service to do that and it is all working fine.
TrustManager[] trustAllCerts = new TrustManager[]{new 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) {
}
}};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (GeneralSecurityException e) {
LOGGER.error(e);
}
Problem:
Since this code is in my service, it is being executed each time a new request is made via this service. Is there a way to make this code execute only once instead of for each request? Some sample with actual code will be really appreciated.
Please comment if any more explanation is required.

You can, for example, put this code into init method of separate Spring bean, it will be executed during startup of your application:
#Component
public class TrustManagerConfigurer {
#PostConstruct
public void installTrustManager() { ... }
}
Alternatively, you can put it into ServletContextListener.contextInitialized() to achieve the same effect.
See also:
3.9.6 #PostConstruct and #PreDestroy

Just save that ServletContext somewhere instead of recreating it every time.
You are aware that this code is radically insecure? and that the proper solution to this issue is to import that certificate into your truststore?

Related

Not able to create client in Java while using apache HTTPS libraries

I am working on an application where I have to send the request to another server running. Whenever I try to create the client so that I can send my API request to server, it stuck there. It doesn't throw exception also and doesn't get executed. That thread just dies without doing anything. I debugged a lot by putting loggers after each line and found out SSL build line is having issues.
If I try to execute same code from local machine, it gets executed cleanly but from my application, it fails. Can someone please let me know what is the exact issue.Here is the code which I have written for creating the client.I think the issue is related to certificates but in verify methods, it is saying setting everything as true.
private HttpClient createClient() throws Exception {
X509TrustManager x509TrustManager = new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
};
TrustManager[] trustManagers = new TrustManager[] {x509TrustManager};
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, trustManagers, new SecureRandom());
// code works fine till here and after that this thread just dies.
return HttpClients.custom().setSSLHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
}).setSSLContext(sslContext).build();
}
The issue was with the version of httpcore version. Since I was using httpclient version greater than 4.5 and I have httpcore version lesser than 4. There were no issues with the code. If someone is creating a client using apache libraries, please make sure you are using versions updated.

Access denied ("javax.net.ssl.SSLPermission" "setDefaultSSLContext")

I am using below code to trust all certificates and the code is running in a containerized environment, I am getting exception as Access denied ("javax.net.ssl.SSLPermission" "setDefaultSSLContext") and same code which is running on normal tomcat server is working fine
URL destinationURL = null;
SSLContext context = null;
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
#Override
public X509Certificate[] getAcceptedIssuers() {
//return new X509Certificate[1];
return null;
}
#Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//DO
}
#Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//DO
}
}
};
try {
context = SSLContext.getInstance("SSL");
context.init(null, trustAllCerts, null);
SSLContext.setDefault(context);
//proxy details here
destinationURL = new URL('url');
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
} catch (Exception e) {
e.printStackTrace();
}
You can use specified SSLContext to build socketfactory which can be used for URL Connections, changing the default one is not recommended.
From SSLContext:
setDefault
Throws: SecurityException - if a security manager exists and its checkPermission method does not allow SSLPermission("setDefaultSSLContext")
This permission is not granted by default, as it is considered unsafe. From SSLPermission:
Malicious code can set a context that monitors the opening of connections or the plaintext data that is transmitted.
The recommended way to change the default SSLContext is via JVM start-up options. However, you're attempting to effectively disable all trust, which is also unsafe and not supported via system properties.
If you're really really sure you want to do this, you'll need to grant your application the necessary permissions. This would e.g. be via a policy file:
grant codeBase "file:/home/ajay/myunsafecode" {
permission javax.net.ssl.SSLPermission "setDefaultSSLContext";
};
Or, just don't change the default SSLContext and use your unsafe one directly.
(all links for JDK 11)

java.lang.IllegalStateException: Unable to extract the trust manager on AndroidPlatform, sslSocketFactory

In my application, I have integrated two libraries i.e. chat and video calling...The problem is when I open video library first, then both chat and video calling libraries are working fine but when I open the chat library first, and then open the video, it leads to an exception...I think it is a problem with sockets with default trustmangers..
Sample code I am using in video calling library to create sslcontext
trustManagers = new TrustManager[]{new X509TrustManager() {
#Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
};
try {
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, null);
} catch (NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
}
The exception I got this:
java.lang.IllegalStateException: Unable to extract the trust manager on AndroidPlatform, sslSocketFactory is class org.conscrypt.OpenSSLSocketFactoryImpl...Please help any one.
In my case it happened on emulator API 16 when I used https://stackoverflow.com/a/50264472/2914140 in this way:
val sslcontext: SSLContext = SSLContext.getInstance("TLSv1.2")
sslcontext.init(null, null, null)
val tlsSocketFactory = TLSSocketFactory()
val okHttpClient = OkHttpClient().newBuilder()
.sslSocketFactory(tlsSocketFactory)
.build()
When I add a trustManager parameter to sslSocketFactory method, the exception disappears. But a problem with SSL connection doesn't disappear.

Java : javax.net.ssl.SSLHandshakeException

Given the following code:
public void start(String a_sAddress, int a_nPort) throws IOException {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
#Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
#Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
// TODO Auto-generated method stub
}
#Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
// TODO Auto-generated method stub
}
} };
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init( null, trustAllCerts, new java.security.SecureRandom() );
// Init a configuration with our SSL context
HttpsConfigurator configurator = new HttpsConfigurator(sslContext);
HttpsServer server = HttpsServer.create(new InetSocketAddress(a_sAddress, a_nPort), 0);
server.setHttpsConfigurator(configurator);
//here - attaching HttpHanlder code.
server.setExecutor(null); // creates a default executor
server.start();
}
catch (KeyManagementException e) {
System.out.println("HttpsRequest - setTLSMode - KeyManagementException");
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
System.out.println("HttpsRequest - setTLSMode - NoSuchAlgorithmException");
e.printStackTrace();
}
}
I was trying to ignore certificate verification, since I am only a test simulator.
The problem is that my client gets "javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake"
Must I handle certificates here? Or am I failing in trying to ignore the certificates validation?
Thank you.
Update: Well, talking to some friends, they suggested I should create a self-signed certificate, register my server with it and send it to my client to use when sending me requests.
My server is running on Solaris 10. I tried to look in
The Most Common Java Keytool Keystore Commands
but couldn't figure out the specific commands which fits my needs.
Can you please assist?
Thanks
You need
keytool -genkey ...
to generate a keypair, and then
keytool -selfcert ...
to generate a self-signed certificate, using the same alias.

Make a connection to a HTTPS server from Java and ignore the validity of the security certificate

I've been testing a system that accesses a group of https servers with different keys, some of which are invalid and all of them are not in the local key store for my JVM. I am really only testing things out, so I don't care about the security at this stage. Is there a good way to make POST calls to the server and tell Java not to worry about the security certificates?
My google searches for this have brought up some code examples that make a class to do the validation, that always works, but I cannot get it to connect to any of the servers.
As per the comments:
With Googled examples, you mean among others this one?
Update: the link broke, so here's an extract of relevance which I saved from the internet archive:
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
}
// Now you can access an https URL without having the certificate in the truststore
try {
URL url = new URL("https://hostname/index.html");
} catch (MalformedURLException e) {
}
You need to create a X509TrustManager which bypass all the security check. You can find an example in my answer to this question,
How to ignore SSL certificate errors in Apache HttpClient 4.0

Categories