How to fix the "java.security.cert.CertificateException: No subject alternative names present" error?

JavaSslHttpsCertificateSsl Certificate

Java Problem Overview


I have a Java web service client, which consumes a web service via HTTPS.

import javax.xml.ws.Service;

@WebServiceClient(name = "ISomeService", targetNamespace = "http://tempuri.org/", wsdlLocation = "...")
public class ISomeService
	extends Service
{

	public ISomeService() {
		super(__getWsdlLocation(), ISOMESERVICE_QNAME);
	}

When I connect to the service URL (https://AAA.BBB.CCC.DDD:9443/ISomeService ), I get the exception java.security.cert.CertificateException: No subject alternative names present.

To fix it, I first ran openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt and got following content in file certs.txt:

CONNECTED(00000003)
---
Certificate chain
 0 s:/CN=someSubdomain.someorganisation.com
   i:/CN=someSubdomain.someorganisation.com
-----BEGIN CERTIFICATE-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=someSubdomain.someorganisation.com
issuer=/CN=someSubdomain.someorganisation.com
---
No client certificate CA names sent
---
SSL handshake has read 489 bytes and written 236 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-MD5
Server public key is 512 bit
Compression: NONE
Expansion: NONE
SSL-Session:
	Protocol  : TLSv1
	Cipher    : RC4-MD5            
	Session-ID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	Session-ID-ctx: 	            
	Master-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	Key-Arg   : None
	Start Time: 1382521838
	Timeout   : 300 (sec)
	Verify return code: 21 (unable to verify the first certificate)
---

AFAIK, now I need to

  1. extract the part of certs.txt between -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----,
  2. modify it so that the certificate name is equal to AAA.BBB.CCC.DDD and
  3. then import the result using keytool -importcert -file fileWithModifiedCertificate (where fileWithModifiedCertificate is the result of operations 1 and 2).

Is this correct?

If so, how exactly can I make the certificate from step 1 work with IP-based adddress (AAA.BBB.CCC.DDD) ?

Update 1 (23.10.2013 15:37 MSK): In an answer to a similar question, I read the following:

> If you're not in control of that server, use its host name (provided > that there is at least a CN matching that host name in the existing > cert).

What exactly does "use" mean?

Java Solutions


Solution 1 - Java

I fixed the problem by disabling HTTPS checks using the approach presented here:

I put following code into the the ISomeService class:

static {
	disableSslVerification();
}

private static void disableSslVerification() {
    try
    {
        // 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(X509Certificate[] certs, String authType) {
            }
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        }
        };

        // Install the all-trusting trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        // Create all-trusting host name verifier
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        // Install the all-trusting host verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }
}

Since I'm using the https://AAA.BBB.CCC.DDD:9443/ISomeService for testing purposes only, it's a good enough solution, but do not do this in production.

Note that you can also disable SSL for "one connection at a time" ex:

 // don't call disableSslVerification but use its internal code:
 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 if (conn instanceof HttpsURLConnection) {
    HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
    httpsConn.setHostnameVerifier(allHostsValid);
    httpsConn.setSSLSocketFactory(sc.getSocketFactory());
 }

Solution 2 - Java

I've the same problem and solved with this code. I put this code before the first call to my webservices.

javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
  new javax.net.ssl.HostnameVerifier(){

      public boolean verify(String hostname,
             javax.net.ssl.SSLSession sslSession) {
          return hostname.equals("localhost"); // or return true
      }
  });

It's simple and works fine.

Here is the original source.

Solution 3 - Java

This is an old question, yet I had the same problem when moving from JDK 1.8.0_144 to jdk 1.8.0_191

We found a hint in the changelog:

Changelog

we added the following additional system property, which helped in our case to solve this issue:

-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true

Solution 4 - Java

The verification of the certificate identity is performed against what the client requests.

When your client uses https://xxx.xxx.xxx.xxx/something (where xxx.xxx.xxx.xxx is an IP address), the certificate identity is checked against this IP address (in theory, only using an IP SAN extension).

If your certificate has no IP SAN, but DNS SANs (or if no DNS SAN, a Common Name in the Subject DN), you can get this to work by making your client use a URL with that host name instead (or a host name for which the cert would be valid, if there are multiple possible values). For example, if you cert has a name for www.example.com, use https://www.example.com/something.

Of course, you'll need that host name to resolve to that IP address.

In addition, if there are any DNS SANs, the CN in the Subject DN will be ignored, so use a name that matches one of the DNS SANs in this case.

Solution 5 - Java

To import the cert:

  1. Extract the cert from the server, e.g. openssl s_client -showcerts -connect AAA.BBB.CCC.DDD:9443 > certs.txt This will extract certs in PEM format.
  2. Convert the cert into DER format as this is what keytool expects, e.g. openssl x509 -in certs.txt -out certs.der -outform DER
  3. Now you want to import this cert into the system default 'cacert' file. Locate the system default 'cacerts' file for your Java installation. Take a look at https://stackoverflow.com/questions/11936685/how-to-obtain-the-location-of-cacerts-of-the-default-java-installation
  4. Import the certs into that cacerts file: sudo keytool -importcert -file certs.der -keystore <path-to-cacerts> Default cacerts password is 'changeit'.

If the cert is issued for an FQDN and you're trying to connect by IP address in your Java code, then this should probably be fixed in your code rather than messing with certificate itself. Change your code to connect by FQDN. If FQDN is not resolvable on your dev machine, simply add it to your hosts file, or configure your machine with DNS server that can resolve this FQDN.

Solution 6 - Java

I fixed this issue in a right way by adding the subject alt names in certificate rather than making any changes in code or disabling SSL unlike what other answers suggest here. If you see clearly the exception says the "Subject alt names are missing" so the right way should be to add them

Please look at this link to understand step by step.

The above error means that your JKS file is missing the required domain on which you are trying to access the application.You will need to Use Open SSL and the key tool to add multiple domains

  1. Copy the openssl.cnf into a current directory

  2. echo '[ subject_alt_name ]' >> openssl.cnf

  3. echo 'subjectAltName = DNS:example.mydomain1.com, DNS:example.mydomain2.com, DNS:example.mydomain3.com, DNS: localhost'>> openssl.cnf

  4. openssl req -x509 -nodes -newkey rsa:2048 -config openssl.cnf -extensions subject_alt_name -keyout private.key -out self-signed.pem -subj '/C=gb/ST=edinburgh/L=edinburgh/O=mygroup/OU=servicing/CN=www.example.com/[email protected]' -days 365

  5. Export the public key (.pem) file to PKS12 format. This will prompt you for password

    openssl pkcs12 -export -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -export -in
    self-signed.pem -inkey private.key -name myalias -out keystore.p12
    
  6. Create a.JKS from self-signed PEM (Keystore)

    keytool -importkeystore -destkeystore keystore.jks -deststoretype PKCS12 -srcstoretype PKCS12 -srckeystore keystore.p12
    
  7. Generate a Certificate from above Keystore or JKS file

    keytool -export -keystore keystore.jks -alias myalias -file selfsigned.crt
    
  8. Since the above certificate is Self Signed and is not validated by CA, it needs to be added in Truststore(Cacerts file in below location for MAC, for Windows, find out where your JDK is installed.)

    sudo keytool -importcert -file selfsigned.crt -alias myalias -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/cacerts
    

Original answer posted on this link here.

Solution 7 - Java

You may not want to disable all ssl Verificatication and so you can just disable the hostName verification via this which is a bit less scary than the alternative:

HttpsURLConnection.setDefaultHostnameVerifier(
    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

[EDIT]

As mentioned by conapart3 SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER is now deprecated, so it may be removed in a later version, so you may be forced in the future to roll your own, although I would still say I would steer away from any solutions where all verification is turned off.

Solution 8 - Java

my problem with getting this error was resolved by using the full URL "qatest.ourCompany.com/webService" instead of just "qatest/webService". Reason was that our security certificate had a wildcard i.e. "*.ourCompany.com". Once I put in the full address the exception went away. Hope this helps.

Solution 9 - Java

We faced a similar issue recently "No subject alternative DNS name matching found", it was a nightmare because we were able to reproduce it only in Production servers, were access to debug is near to zero. The rest of environments were just working fine. Our stack was JDK 1.8.x+, JBoss EAP 7+, Java Spring Boot app and Okta as identity provider (the SSL handshake was failing when recovering the well-known configuration from Okta, where okta is available in AWS Cloud - virtual servers).

Finally, we discover that (no one knows why) the JBoss EAP application server that we were using it was having an additional JVM System Property:

jsse.enableSNIExtension = false

This was preventing to establish TLS connection and we were able to reproduce the issue by adding that same system property/value in other environments. So the solution was simple to remove that undesired property and value.

As per Java Security Doc, this property is set by default to true for Java 7+ (refer to https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#InstallationAndCustomization)

> * jsse.enableSNIExtension system property. Server Name Indication (SNI) is a TLS extension, defined in RFC 4366. It enables TLS connections to virtual servers, in which multiple servers for different network names are hosted at a single underlying network address. Some very old SSL/TLS vendors may not be able handle SSL/TLS extensions. In this case, set this property to false to disable the SNI extension.

Solution 10 - Java

Have answered it already in https://stackoverflow.com/a/53491151/1909708.

This fails because neither the certificate common name (CN in certification Subject) nor any of the alternate names (Subject Alternative Name in the certificate) match with the target hostname or IP adress.

For e.g., from a JVM, when trying to connect to an IP address (WW.XX.YY.ZZ) and not the DNS name (https://stackoverflow.com), the HTTPS connection will fail because the certificate stored in the java truststore cacerts expects common name (or certificate alternate name like stackexchange.com or *.stackoverflow.com etc.) to match the target address.

Please check: https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#HostnameVerifier

    HttpsURLConnection urlConnection = (HttpsURLConnection) new URL("https://WW.XX.YY.ZZ/api/verify").openConnection();
    urlConnection.setSSLSocketFactory(socketFactory());
    urlConnection.setDoOutput(true);
    urlConnection.setRequestMethod("GET");
    urlConnection.setUseCaches(false);
    urlConnection.setHostnameVerifier(new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession sslSession) {
            return true;
        }
    });
    urlConnection.getOutputStream();

Above, passed an implemented HostnameVerifier object which is always returns true:

new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession sslSession) {
            return true;
        }
    }

Solution 11 - Java

As some one pointed before, I added the following code (with lambda) just before creating the RestTemplate object, and it works fine. IT is only for my internal testing class, so I will work around with a better solution for the production code.

javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
            (hostname, sslSession) -> true);

Solution 12 - Java

For Spring Boot RestTemplate:

  • add org.apache.httpcomponents.httpcore dependency

  • use NoopHostnameVerifier for SSL factory:

      SSLContext sslContext = new SSLContextBuilder()
              .loadTrustMaterial(new URL("file:pathToServerKeyStore"), storePassword)
      //        .loadKeyMaterial(new URL("file:pathToClientKeyStore"), storePassword, storePassword)
              .build();
      SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
      CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(socketFactory).build();
      HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(client);
      RestTemplate restTemplate = new RestTemplate(factory);
    

Solution 13 - Java

> This code will work like charm and use the restTemple object for rest of the code.

  RestTemplate restTemplate = new RestTemplate();   
  TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
            @Override
            public boolean isTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) {
                return true;
            }

        };

        SSLContext sslContext = null;
        try {
            sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy)
                    .build();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(httpClient);
        
        restTemplate.setRequestFactory(requestFactory);
}

Solution 14 - Java

I also faced the same issue with a self signed certificate . By referring to few of the above solutions , i tried regenerating the certificate with the correct CN i.e the IP Address of the server .But still it didn't work for me . Finally i tried regenerating the certificate by adding the SAN address to it via the below mentioned command

**keytool -genkey -keyalg RSA -keystore keystore.jks -keysize 2048 -alias <IP_ADDRESS> -ext san=ip:<IP_ADDRESS>**

After that i started my server and downloaded the client certificates via the below mentioned openssl command

**openssl s_client -showcerts -connect <IP_ADDRESS>:443 < /dev/null | openssl x509 -outform PEM > myCert.pem**

Then i imported this client certificate to the java default keystore file (cacerts) of my client machine by the below mentioned command

**keytool -import -trustcacerts -keystore /home/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-1.el7.x86_64/jre/lib/security/cacerts -alias <IP_ADDRESS> -file ./mycert.pem**

Solution 15 - Java

I got to this question after if got this same error message. However in my case we had two URL's with different subdomains (http://example1.xxx.com/someservice and http://example2.yyy.com/someservice) which were directed to the same server. This server was having only one wildcard certificate for the *.xxx.com domain. When using the service via the second domain, the found certicate (*.xxx.com) does not match with the requested domain (*.yyy.com) and the error occurs.

In this case we should not try to fix such an errormessage by lowering SSL security, but should check the server and certificates on it.

Solution 16 - Java

I was going through 2 way SSL in springboot. I have made all correct configuration service tomcat server and service caller RestTemplate. but I was getting error as "java.security.cert.CertificateException: No subject alternative names present"

After going through solutions, I found, JVM needs this certificate otherwise it gives handshaking error.

Now, how to add this to JVM.

go to jre/lib/security/cacerts file. we need to add our server certificate file to this cacerts file of jvm.

Command to add server cert to cacerts file via command line in windows.

C:\Program Files\Java\jdk1.8.0_191\jre\lib\security>keytool -import -noprompt -trustcacerts -alias sslserver -file E:\spring_cloud_sachin\ssl_keys\sslserver.cer -keystore cacerts -storepass changeit

Check server cert is installed or not:

C:\Program Files\Java\jdk1.8.0_191\jre\lib\security>keytool -list -keystore cacerts

you can see list of certificates installed:

for more details: https://sachin4java.blogspot.com/2019/08/javasecuritycertcertificateexception-no.html

Solution 17 - Java

add the host entry with the ip corresponding to the CN in the certificate

CN=someSubdomain.someorganisation.com

now update the ip with the CN name where you are trying to access the url.

It worked for me.

Solution 18 - Java

When you have a certificate with both CN and Subject Alternative Names (SAN), if you make your request based on the CN content, then that particular content must also be present under SAN, otherwise it will fail with the error in question.

In my case CN had something, SAN had something else. I had to use SAN URL, and then it worked just fine.

Solution 19 - Java

I have resolved the said

> MqttException (0) - javax.net.ssl.SSLHandshakeException: No > subjectAltNames on the certificate match

error by adding one (can add multiple) alternative subject name in the server certificate (having CN=example.com) which after prints the part of certificate as below:

Subject Alternative Name:
DNS: example.com

I used KeyExplorer on windows for generating my server certificate. You can follow this link for adding alternative subject names (follow the only part for adding it).

Solution 20 - Java

I was referred to animo3991's answer and tweaked it to make my Bitbucket Backup Client 3.6.0 work for backing up my Bitbucket Server when before it was also hitting No subject alternative names present error.

The first command however must use alias tomcat, otherwise Bitbucket Server would not start up properly:

keytool -genkey -keyalg RSA -sigalg SHA256withRSA -keystore keystore.jks -keysize 2048 -alias tomcat -ext san=ip:<IP_ADDRESS>

openssl s_client -showcerts -connect <IP_ADDRESS>:443 < /dev/null | openssl x509 -outform PEM > myCert.pem

keytool -import -trustcacerts -keystore /etc/pki/ca-trust/extracted/java/cacerts -alias <IP_ADDRESS> -file ./myCert.pem

Solution 21 - Java

public class RESTfulClientSSL {

    static TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            // TODO Auto-generated method stub
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            // TODO Auto-generated method stub
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }
    }};

    public class NullHostNameVerifier implements HostnameVerifier {
        /*
         * (non-Javadoc)
         *
         * @see javax.net.ssl.HostnameVerifier#verify(java.lang.String,
         * javax.net.ssl.SSLSession)
         */
        @Override
        public boolean verify(String arg0, SSLSession arg1) {
            // TODO Auto-generated method stub
            return true;
        }
    }

    public static void main(String[] args) {

        HttpURLConnection connection = null;
        try {

            HttpsURLConnection.setDefaultHostnameVerifier(new RESTfulwalkthroughCer().new NullHostNameVerifier());
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());


            String uriString = "https://172.20.20.12:9443/rest/hr/exposed/service";
            URL url = new URL(uriString);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            //connection.setRequestMethod("POST");

            BASE64Encoder encoder = new BASE64Encoder();
            String username = "admin";
            String password = "admin";
            String encodedCredential = encoder.encode((username + ":" + password).getBytes());
            connection.setRequestProperty("Authorization", "Basic " + encodedCredential);

            connection.connect();
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                StringBuffer stringBuffer = new StringBuffer();
                String line = "";
                while ((line = reader.readLine()) != null) {
                    stringBuffer.append(line);
                }
                String content = stringBuffer.toString();
                System.out.println(content);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
}

Solution 22 - Java

Add your IP address in the hosts file.which is in the folder of C:\Windows\System32\drivers\etc. Also add IP and Domain Name of the IP address. example: aaa.bbb.ccc.ddd [email protected]

Solution 23 - Java

I have solved the issue by the following way.

  1. Creating a class . The class has some empty implementations

class MyTrustManager implements X509TrustManager {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
	return null;
}

public void checkClientTrusted(X509Certificate[] certs, String authType) {
}

public void checkServerTrusted(X509Certificate[] certs, String authType) {
}

@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString)
		throws CertificateException {
	// TODO Auto-generated method stub

}

@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString)
		throws CertificateException {
	// TODO Auto-generated method stub

}

  1. Creating a method

private static void disableSSL() {
	try {
		TrustManager[] trustAllCerts = new TrustManager[] { new MyTrustManager() };

		// Install the all-trusting trust manager
		SSLContext sc = SSLContext.getInstance("SSL");
		sc.init(null, trustAllCerts, new java.security.SecureRandom());
		HostnameVerifier allHostsValid = new HostnameVerifier() {
			public boolean verify(String hostname, SSLSession session) {
				return true;
			}
		};
		HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
		HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
	} catch (Exception e) {
		e.printStackTrace();
	}
}

  1. Call the disableSSL() method where the exception is thrown. It worked fine.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPDPView Question on Stackoverflow
Solution 1 - JavaPDPView Answer on Stackoverflow
Solution 2 - JavajuanmhidalgoView Answer on Stackoverflow
Solution 3 - JavadiswutzView Answer on Stackoverflow
Solution 4 - JavaBrunoView Answer on Stackoverflow
Solution 5 - JavaandreycppView Answer on Stackoverflow
Solution 6 - JavaAbhishek GalodaView Answer on Stackoverflow
Solution 7 - JavalifesoordinaryView Answer on Stackoverflow
Solution 8 - JavaShahriarView Answer on Stackoverflow
Solution 9 - JavaCesar MartinezView Answer on Stackoverflow
Solution 10 - JavaHimadri PantView Answer on Stackoverflow
Solution 11 - JavaShehan SimenView Answer on Stackoverflow
Solution 12 - JavaGrigory KislinView Answer on Stackoverflow
Solution 13 - JavaNizam MahammadView Answer on Stackoverflow
Solution 14 - Javaanimo3991View Answer on Stackoverflow
Solution 15 - JavaGertView Answer on Stackoverflow
Solution 16 - JavaSachin RaneView Answer on Stackoverflow
Solution 17 - JavamanojView Answer on Stackoverflow
Solution 18 - JavaTudorView Answer on Stackoverflow
Solution 19 - JavaManishoahamView Answer on Stackoverflow
Solution 20 - JavaVolcan BaruView Answer on Stackoverflow
Solution 21 - Javauser11888077View Answer on Stackoverflow
Solution 22 - JavaPrakash SoniView Answer on Stackoverflow
Solution 23 - JavaAditya BhuyanView Answer on Stackoverflow