The SSL (Secure Socket Layer) is used for a encrypted communication between client and server. To use SSL, server is configured with a certificate. The certificate contains public and private keys for encryption. Theses are necessary for SSL handshaking (creating a connection). But sometimes you can get a SSLHandshakeException or to be specific CertPathValidatorException.
There can be three reasons for the exception namely
- An unknown CA issued the certificate.
- Missing intermediate certificate.
- Self-signed certificate.
To resolve the issue I used a simple technique with my Retrofit-2 request. I saved the certificate on my end as raw resource and used it in the request to the server.
We have to create a SSLContext to pass it in our request.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
try { CertificateFactory mCertificateFactory = CertificateFactory.getInstance("X.509"); InputStream mInputStream = getResources().openRawResource(R.raw.certificate); Certificate mCertificate = mCertificateFactory.generateCertificate(mInputStream); String defaultKeyStore = KeyStore.getDefaultType(); KeyStore mKeyStore = KeyStore.getInstance(defaultKeyStore); mKeyStore.load(null, null); mKeyStore.setCertificateEntry("ca", mCertificate); String defaultAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory mTrustManagerFactory= TrustManagerFactory.getInstance(defaultAlgorithm); mTrustManagerFactory.init(mKeyStore); SSLContext mSSLContext = SSLContext.getInstance("TLS"); mSSLContext.init(null, mTrustManagerFactory.getTrustManagers(), null); } catch (Exception e) { e.printStackTrace(); } |
Now using this SSLContext create a SSLSocketFactory object and assign it to your connection request as
1 |
okHttpConnection.setSSLSocketFactory(mSSLContext.getSocketFactory()); |
And with that all your errors/ exceptions are gone and you can securely call your HTTP requests to the server.