1

I have got a server with self-signed certificate. I've imported it with a keytool on my computer and use

-Djavax.net.ssl.trustStore=blabla

compile argument. When I try to run the following code:

SSLSocketFactory factory = HttpsURLConnection.getDefaultSSLSocketFactory();
SSLSocket socket = (SSLSocket) factory.createSocket("MY_URL_DIGITS", 443);
OutputStream os = socket.getOutputStream();
os.write("Test request \n".getBytes());
os.flush();
os.close();

Everything goes alright and I can see the "Test request" on the server. However, when I run:

URL url = new URL("https://MY_URL_DIGITS");
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
OutputStream os = con.getOutputStream();
os.write("Test request \n".getBytes());
os.flush();
os.close();

I've got the

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present

So what is the principal difference between these two snippets?

Dmitrii Bocharov
  • 872
  • 6
  • 21

2 Answers2

1

The difference is that HTTPS adds a step, which can be seen in the HostnameVerifier interface. It is trying to match the hostname being connected to with the hostname in the SubjectDN or alternative names.

user207421
  • 305,947
  • 44
  • 307
  • 483
1

SSLSocket by default only checks whether you trust the certificate. HttpsURLConnection checks whether you trust the certificate and also checks whether the certificate says it is coming from the same place you actually navigated to. For your HttpsURLConnection to succeed, the certificate would have to specify a subject alternative name (SAN) that was the same as the server you are conecting to. In this case the SAN would need to be "dns:MY_URL_DIGITS", where the "dns" part says you are specifying a host name rather than an IP address.

If you need additional information on how to create a certificate with a subject alternative name, see:

how to add subject alernative name to ssl certs?

Community
  • 1
  • 1
Warren Dew
  • 8,790
  • 3
  • 30
  • 44