Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 644
just_user Avatar asked Aug 10 '15 11:08

just_user


People also ask

How do I fix SSLPeerUnverifiedException?

The solution is to use ProviderInstaller from Google Play Services to try to update the device to support the latest and greatest security protocols.

What is SSLPeerUnverifiedException?

Class SSLPeerUnverifiedExceptionIndicates that the peer's identity has not been verified.


2 Answers

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;             }         }); 
like image 121
Jake Hall Avatar answered Sep 22 '22 18:09

Jake Hall


I finally got this working with a mix of multiple answers.

First, the certificates was made wrongly, not sure how. But by creating them using the script in this answer made them work. What was needed was a server certificate and a key. Then the client needed another certificate.

To use the certificate in android I converted the .pem file to a .crt file like this:

openssl x509 -outform der -in client.pem  -out client.crt 

In android I added the certificate to my OkHttp client like the following:

public ApiService() {     mClient = new OkHttpClient();     mClient.setConnectTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS);     mClient.setReadTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS);     mClient.setCache(getCache());     mClient.setSslSocketFactory(getSSL()); }  protected SSLSocketFactory getSSL() {     try {         CertificateFactory cf = CertificateFactory.getInstance("X.509");         InputStream cert = getAppContext().getResources().openRawResource(R.raw.client);         Certificate ca = cf.generateCertificate(cert);         cert.close();          // creating a KeyStore containing our trusted CAs         String keyStoreType = KeyStore.getDefaultType();         KeyStore keyStore = KeyStore.getInstance(keyStoreType);         keyStore.load(null, null);         keyStore.setCertificateEntry("ca", ca);          return new AdditionalKeyStore(keyStore);     } catch(Exception e) {         e.printStackTrace();     }     return null; } 

The last part with new AdditionalKeyStore() is taken from this very well written answer. Which adds a fallback keystore.

I hope this might help anyone else! This is the simplest way to get HTTPS working with a self-signed certificate that I have found. Other ways include having a BouncyCastle keystore which seems excessive to me.

like image 29
just_user Avatar answered Sep 23 '22 18:09

just_user