From ba8166fec12164aac68fffe555ebc782d5ca1d14 Mon Sep 17 00:00:00 2001 From: Syd Logan Date: Wed, 13 Jun 2018 21:40:06 -0700 Subject: [PATCH] first stab at supporting SSL certificate pinning --- .../tscharts_lib/TrustedSSLSocketFactory.java | 88 +++++++++++++++++++ .../tscharts_lib/VolleySingleton.java | 21 +++-- app/src/main/res/raw/cert | 0 3 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/org/thousandsmiles/tscharts_lib/TrustedSSLSocketFactory.java create mode 100644 app/src/main/res/raw/cert diff --git a/app/src/main/java/org/thousandsmiles/tscharts_lib/TrustedSSLSocketFactory.java b/app/src/main/java/org/thousandsmiles/tscharts_lib/TrustedSSLSocketFactory.java new file mode 100644 index 0000000..c22dfd6 --- /dev/null +++ b/app/src/main/java/org/thousandsmiles/tscharts_lib/TrustedSSLSocketFactory.java @@ -0,0 +1,88 @@ +package org.thousandsmiles.tscharts_lib; + +import android.content.Context; + +import java.io.BufferedInputStream; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManagerFactory; + +public class TrustedSSLSocketFactory { + + private static SSLSocketFactory m_sf = null; + private static TrustedSSLSocketFactory m_instance = null; + + public static TrustedSSLSocketFactory getInstance() { + if (m_instance == null) { + m_instance = new TrustedSSLSocketFactory(); + } + return m_instance; + } + + public SSLSocketFactory getSocketFactory(Context aCtx) { + + CertificateFactory cf = null; + + if (m_sf != null) { + return m_sf; + } + try { + cf = CertificateFactory.getInstance("X.509"); + } catch (CertificateException e) { + return null; + } + + Certificate ca = null; + // Generate the certificate using the certificate file under res/raw/cert.cer + InputStream caInput = new BufferedInputStream(aCtx.getResources().openRawResource(R.raw.cert)); + try { + ca = cf.generateCertificate(caInput); + try { + caInput.close(); + } catch(java.io.IOException e) { + } + } catch (CertificateException e) { + return null; + } + + // Create a KeyStore containing our trusted CAs + String keyStoreType = KeyStore.getDefaultType(); + KeyStore trusted = null; + try { + trusted = KeyStore.getInstance(keyStoreType); + trusted.load(null, null); + trusted.setCertificateEntry("ca", ca); + } catch (java.security.NoSuchAlgorithmException | java.security.KeyStoreException | java.io.IOException | java.security.cert.CertificateException e ) { + return null; + } + + // Create a TrustManager that trusts the CAs in our KeyStore + String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); + TrustManagerFactory tmf = null; + try { + tmf = TrustManagerFactory.getInstance(tmfAlgorithm); + tmf.init(trusted); + } catch (java.security.KeyStoreException | java.security.NoSuchAlgorithmException e) { + return null; + } + + // Create an SSLContext that uses our TrustManager + SSLContext context = null; + + try { + context = SSLContext.getInstance("TLS"); + context.init(null, tmf.getTrustManagers(), null); + } catch (java.security.KeyManagementException | java.security.NoSuchAlgorithmException e) { + return null; + } + + m_sf = context.getSocketFactory(); + return m_sf; + } +} diff --git a/app/src/main/java/org/thousandsmiles/tscharts_lib/VolleySingleton.java b/app/src/main/java/org/thousandsmiles/tscharts_lib/VolleySingleton.java index c7bf72d..a3dda45 100644 --- a/app/src/main/java/org/thousandsmiles/tscharts_lib/VolleySingleton.java +++ b/app/src/main/java/org/thousandsmiles/tscharts_lib/VolleySingleton.java @@ -20,27 +20,32 @@ import android.content.Context; import com.android.volley.RequestQueue; +import com.android.volley.toolbox.HurlStack; import com.android.volley.toolbox.Volley; +import javax.net.ssl.SSLSocketFactory; + public class VolleySingleton { - private static VolleySingleton instance; - private static RequestQueue queue; + private static VolleySingleton m_instance; + private static RequestQueue m_queue; public void initQueueIf(Context context) { - if (queue == null) { - queue = Volley.newRequestQueue(context); + if (m_queue == null) { + TrustedSSLSocketFactory tssf = TrustedSSLSocketFactory.getInstance(); + SSLSocketFactory sf = tssf.getSocketFactory(context); + m_queue = Volley.newRequestQueue(context, new HurlStack(null, sf)); } } public RequestQueue getQueue() { - return queue; + return m_queue; } public static VolleySingleton getInstance() { - if (instance == null) { - instance = new VolleySingleton(); + if (m_instance == null) { + m_instance = new VolleySingleton(); } - return instance; + return m_instance; } } diff --git a/app/src/main/res/raw/cert b/app/src/main/res/raw/cert new file mode 100644 index 0000000..e69de29