title: Android Https Connection with self signed certificate : hostName not verified
body: <p>Hi I am testing Android connecion with certificate.
  I have created a default ssl server on my ubuntu desktop. Enabled ssl and created the default self-signed certificate. I have then connected to <code>https://localhost</code> with firefox, added certificate to exceptions and then I used Firefox to save cerificate as .pem file.
  I added certificate.pem to my android projetc in res/raw</p>
  
  <p>I have gotten this code from android developer website to connect via https using my certificate (I don't want to trust everything I just want to verify if certicate is correct using the certificate in raw folder).</p>
  
  <p>So when I connect I get:
  java.lang.RuntimeException: java.io.IOException: Hostname '192.168.1.111' was not verified</p>
  
  <p>Here is the class I use to verify the certificate</p>
  
  <pre><code>public class VerifyKey extends AsyncTask&lt;Void, Void, Void&gt;{
  
      public static final String CERTIFICATE_TYPE_X_509 = "X.509";
      public static final String CERTIFICATE_ALIAS = "user_desktop";
      public static final String SERVER_URL = "https://192.168.1.111";
      @Override
      protected Void doInBackground(Void... params) {
          // Load CAs from an InputStream
          // (could be from a resource or ByteArrayInputStream or ...)
          CertificateFactory cf = null;
          InputStream certificateInputStream = getApplicationContext().getResources().openRawResource(R.raw.user_desktop);
          Certificate certificate = null;
          try {
              cf = CertificateFactory.getInstance(CERTIFICATE_TYPE_X_509);
              certificate = cf.generateCertificate(certificateInputStream);
              Log.d(TAG, "Certificate : " + certificate.toString());
              Log.d(TAG, "Certificate public key : " + certificate.getPublicKey());
          } catch (CertificateException e) {
              throw new RuntimeException(e);
          } finally {
              if (certificateInputStream != null) {
                  try {
                      certificateInputStream.close();
                  } catch (IOException e) {
                      throw new RuntimeException(e);
                  }
              }
          }
  
          // Create a KeyStore containing our trusted CAs
          String keyStoreType = KeyStore.getDefaultType();
          KeyStore keyStore = null;
          try {
              keyStore = KeyStore.getInstance(keyStoreType);
              if (keyStore != null) {
                  keyStore.load(null, null);
                  keyStore.setCertificateEntry(CERTIFICATE_ALIAS, certificate);
              } else {
                  throw new RuntimeException("KeyStore is null");
              }
          } catch (KeyStoreException e) {
              throw new RuntimeException(e);
          } catch (CertificateException e) {
              throw new RuntimeException(e);
          } catch (NoSuchAlgorithmException e) {
              throw new RuntimeException(e);
          } catch (IOException e) {
              throw new RuntimeException(e);
          }
  
          // Create a TrustManager that trusts the CAs in our KeyStore
          String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
          TrustManagerFactory tmf = null;
          try {
              tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
              if (tmf != null) {
                  tmf.init(keyStore);
              } else {
                  throw new RuntimeException("TrustManagerFactory is null");
              }
          } catch (NoSuchAlgorithmException e) {
              throw new RuntimeException(e);
          } catch (KeyStoreException e) {
              throw new RuntimeException(e);
          }
  
          // Create an SSLContext that uses our TrustManager
          SSLContext sslContext = null;
          try {
              sslContext = SSLContext.getInstance("TLS");
  
              TrustManager[] trustManagers = tmf.getTrustManagers();
              sslContext.init(null, trustManagers, null);
  
          } catch (NoSuchAlgorithmException e) {
              throw new RuntimeException(e);
          } catch (KeyManagementException e) {
              throw new RuntimeException(e);
          }
  
          // Tell the URLConnection to use a SocketFactory from our SSLContext
          URL url = null;
          HttpsURLConnection httpsURLConnection =
                  null;
          InputStream in = null;
          try {
              url = new URL(SERVER_URL);
              Log.d(TAG, "URL : "+url.toString());
              httpsURLConnection = (HttpsURLConnection)url.openConnection();
              SSLSocketFactory socketFactory = sslContext.getSocketFactory();
              Log.d(TAG, "Socket factory : "+socketFactory.toString());
              httpsURLConnection.setSSLSocketFactory(socketFactory);
  
              in = httpsURLConnection.getInputStream(); //IOException exception gets triggered here
  
              Toast.makeText(getApplicationContext(), in.toString(), Toast.LENGTH_SHORT).show();
          } catch (MalformedURLException e) {
              throw new RuntimeException(e);
          } catch (SSLHandshakeException e){
              throw new RuntimeException(e);
          } catch(UnknownHostException e){
              throw new RuntimeException(e);
          } catch (ConnectException e1){
              throw new RuntimeException(e1);
          } catch (IOException e) {
              throw new RuntimeException(e);
          }
          return null;
      }
  }
  </code></pre>
  
  <p>I have gotten this code from <a href="http://developer.android.com/training/articles/security-ssl.html#SelfSigned" rel="nofollow">http://developer.android.com/training/articles/security-ssl.html#SelfSigned</a></p>
  
  <p>I get this error on Samsung Galaxy s4 with Android 4.3</p>
  
  <p>I don't have a lot of experience with HTTPS so here what I would like to achieve is povide certificate with the app which will allow to verify the server certificate. 
  Please if someone can suggest what I can modify in the code.</p>
  
  <p>I also have a doubt because my server is a .local server but I connect using ip and the objective is to be able to connect using both ip a hostname, will that be problem when veryfying the hostname?
  Thanks a lot in advance </p>
  
  <p>EDIT: I have added code to get the hostname:</p>
  
  <pre><code>InetAddress addr = InetAddress.getByName(SERVER_URL);
  String hostName = addr.getHostName();
  </code></pre>
  
  <p>I have tried using the hostname instead of ip but still I get the same exception:</p>
  
  <pre><code>Caused by: java.io.IOException: Hostname '&lt;user.hostname.com&gt;' was not verified
      at libcore.net.http.HttpConnection.verifySecureSocketHostname(HttpConnection.java:223)
      at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:446)
      at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
      at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
      at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
      at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
      at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)
  </code></pre>