Issue
I am trying to build a login page. For that, I want to open a SSL socket and make a HTTPS request,but I'm getting Unknown Host Exception in the line
SSLSocket skt = (SSLSocket)sslsf.createSocket("https://31.21.18.222/room_info/x.txt" , 443);
Could someone please tell me what I'm doing wrong? Also, I've turned off host verification because it wont be needed in my program.
`public void clickLogin() throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
URL url = new URL ("https://31.21.18.222/room_info/x.txt");
HttpsURLConnection connection = null;
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null); //Make an empty store
InputStream fis = new FileInputStream("C:/Documents and Settings/user/Desktop/PK/localhost.crt");
BufferedInputStream bis = new BufferedInputStream(fis);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
while (bis.available() > 0) {
java.security.cert.Certificate cert = cf.generateCertificate(bis);
keyStore.setCertificateEntry("localhost", cert);
}
// write code for turning off client verification
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(keyStore);
SSLContext context = SSLContext.getInstance("SSL");
context.init(null, tmf.getTrustManagers() , null);
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
SSLSocketFactory sslsf = context.getSocketFactory();
SSLSocket skt = (SSLSocket)sslsf.createSocket("https://31.21.18.222/room_info/x.txt" , 443);
skt.setUseClientMode(true);
SSLSession s = skt.getSession(); // handshake implicitly done
skt.setKeepAlive(true);
connection = (HttpsURLConnection) url.openConnection();
// Host name verification off
connection.setHostnameVerifier(new HostnameVerifier()
{
public boolean verify(String hostname, SSLSession session)
{
return true;
}
}); `
Solution
If you want to open a socket with createSocket
, you need to use the host name (or IP address), not the full URL:
example : sslsf.createSocket("31.21.18.222" , 443);
In addition:
- Don't use
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider())
(it's there by default). - It's probably better to use
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
instead ofX.509
, especially because the default algorithm for the TMF isPKIX
, notX.509
. createSocket
will verify the certificate against the trust anchors, but won't check the host name (which is also required to prevent MITM attacks). For this, it's also generally better to use a host name instead of an IP address.
Answered By - Bruno
Answer Checked By - Senaida (JavaFixing Volunteer)