OkHttp javax.net.ssl.SSLPeerUnverifiedException: Hostname domain.com not verified

just_user picture just_user · Aug 10, 2015 · Viewed 40.8k times · Source

I've been trying for days to get this working. I'm trying to connect to my server over https with a self signed certificate. I don't think there is any pages or examples that I haven't read by now.

What I have done:

  1. Created bks keystore by following this tutorial: http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

It uses openssl s_client -connect domain.com:443 to get the certificate from the server. Then creates a bks keystore using bouncy castle.

  1. Reading created keystore from raw folder adding it to sslfactory and and then to OkHttpClient. Like this:

    public ApiService() {
        mClient = new OkHttpClient();
        mClient.setConnectTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS);
        mClient.setReadTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS);
        mClient.setCache(getCache());
        mClient.setCertificatePinner(getPinnedCerts());
        mClient.setSslSocketFactory(getSSL());
    }
    
    protected SSLSocketFactory getSSL() {
        try {
            KeyStore trusted = KeyStore.getInstance("BKS");
            InputStream in = Beadict.getAppContext().getResources().openRawResource(R.raw.mytruststore);
            trusted.load(in, "pwd".toCharArray());
            SSLContext sslContext = SSLContext.getInstance("TLS");
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(trusted);
            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
            return sslContext.getSocketFactory();
        } catch(Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public CertificatePinner getPinnedCerts() {
        return new CertificatePinner.Builder()
                .add("domain.com", "sha1/theSha=")
                .build();
    }
    
  2. This for some reason this always generates a SSLPeerUnverifiedException with or without the keystore. And with or without the CertificatePinner.

    javax.net.ssl.SSLPeerUnverifiedException: Hostname domain.com not verified: 0         
     W/System.err﹕ certificate: sha1/theSha=
     W/System.err﹕ DN: 1.2.840.113549.1.9.1=#1610696e666f40626561646963742e636f6d,CN=http://domain.com,OU=development,O=domain,L=Valencia,ST=Valencia,C=ES
     W/System.err﹕ subjectAltNames: []
     W/System.err﹕ at com.squareup.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:124)
     W/System.err﹕ at com.squareup.okhttp.Connection.connect(Connection.java:143)
     W/System.err﹕ at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:185)
     W/System.err﹕ at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128)
     W/System.err﹕ at com.squareup.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:341)
     W/System.err﹕ at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330)
     W/System.err﹕ at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
     W/System.err﹕ at com.squareup.okhttp.Call.getResponse(Call.java:273)
     W/System.err﹕ at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:230)
     W/System.err﹕ at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:201)
     W/System.err﹕ at com.squareup.okhttp.Call.execute(Call.java:81)
     ...
    

What am I doing wrong?

Answer

Jake Hall picture Jake Hall · Sep 4, 2015

I had the same problem, however I needed my application to work on several staging environments, all of which had self signed certs. To make matters worse, they could change those certs on the fly.

To fix this, when connecting to staging only, I added a SSLSocketFactory which trusted all certs. This fixed the java error, however it left me with the okhttp exception noted in this ticket.

To avoid this error, I needed to add one more customization to my okHttpClient. This fixed the error for me.

okHttpClient.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });