{"id":7720,"date":"2015-10-19T00:57:36","date_gmt":"2015-10-19T00:57:36","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2015\/10\/19\/how-can-i-pin-a-certificate-with-square-okhttp-open-source-projects-square-okhttp\/"},"modified":"2015-10-19T00:57:36","modified_gmt":"2015-10-19T00:57:36","slug":"how-can-i-pin-a-certificate-with-square-okhttp-open-source-projects-square-okhttp","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2015\/10\/19\/how-can-i-pin-a-certificate-with-square-okhttp-open-source-projects-square-okhttp\/","title":{"rendered":"How can I pin a certificate with Square OKHTTP?-open source projects square\/okhttp"},"content":{"rendered":"<p>After reading this blog post I was able to modify the concept for use with OkHttp. You should use at least version 2.0 if you want to avoid using a global SSL context.<\/p>\n<p>This modification applies only to the current instance of OkHttp, and changes that instance so that it <strong>only<\/strong> accepts certificates from the certificate specified. If you want other certificates (such as one from Twitter) to be accepted, you simply need to create a new OkHttp instance without the modifications described below.<\/p>\n<h2>1. Creating a TrustStore<\/h2>\n<p>In order to pin a certificate, you first need to create a truststore containing this certificate. To create the truststore we will use this handy script from nelenkov slightly modified for our purposes:<\/p>\n<pre><code>#!\/bin\/bash\n\nif [ \"$#\" -ne 3 ]; then\n  echo \"Usage: importcert.sh   \"\n  exit 1\nfi\n\nCACERT=$1\nBCJAR=$2\nSECRET=$3\n\nTRUSTSTORE=mytruststore.bks\nALIAS=`openssl x509 -inform PEM -subject_hash -noout -in $CACERT`\n\nif [ -f $TRUSTSTORE ]; then\n    rm $TRUSTSTORE || exit 1\nfi\n\necho \"Adding certificate to $TRUSTSTORE...\"\nkeytool -import -v -trustcacerts -alias $ALIAS \\\n      -file $CACERT \\\n      -keystore $TRUSTSTORE -storetype BKS \\\n      -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider \\\n      -providerpath $BCJAR \\\n      -storepass $SECRET\n\necho \"\" \necho \"Added '$CACERT' with alias '$ALIAS' to $TRUSTSTORE...\"\n<\/code><\/pre>\n<p>To run this script you need 3 things:<\/p>\n<ol>\n<li>Make sure <code>keytool<\/code> (included in Android SDK) is on your $PATH.<\/li>\n<li>Make sure you have the latest BouncyCastle jar file download in the same dir as the script. (Download here)<\/li>\n<li>The certificate you want to pin.<\/li>\n<\/ol>\n<p>Now run the script<\/p>\n<pre><code>.\/gentruststore.sh your_cert.pem bcprov-jdk15on-150.jar your_secret_pass\n<\/code><\/pre>\n<p>Type &#8216;yes&#8217; to trust the certificate, and when complete <code>mytruststore.bks<\/code> will be generated in your current dir.<\/p>\n<h2>2. Apply your TrustStore to your Android project<\/h2>\n<p>Create a directory <code>raw<\/code> under your <code>res<\/code> folder. Copy <code>mytruststore.bks<\/code> here.<\/p>\n<p>Now here&#8217;s a very simple class that pins your cert to OkHttp<\/p>\n<pre><code>import android.content.Context;\nimport android.util.Log;\n\nimport com.squareup.okhttp.OkHttpClient;\nimport com.squareup.okhttp.Request;\nimport com.squareup.okhttp.Response;\n\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.security.KeyStore;\n\nimport javax.net.ssl.SSLContext;\nimport javax.net.ssl.SSLSocketFactory;\nimport javax.net.ssl.TrustManagerFactory;\n\n\n\/**\n * Created by martin on 02\/06\/14.\n *\/\npublic class Pinning {\n\n    Context context;\n    public static String TRUST_STORE_PASSWORD = \"your_secret\";\n    private static final String ENDPOINT = \"https:\/\/api.yourdomain.com\/\";\n\n    public Pinning(Context c) {\n        this.context = c;\n    }\n\n    private SSLSocketFactory getPinnedCertSslSocketFactory(Context context) {\n        try {\n            KeyStore trusted = KeyStore.getInstance(\"BKS\");\n            InputStream in = context.getResources().openRawResource(R.raw.mytruststore);\n            trusted.load(in, TRUST_STORE_PASSWORD.toCharArray());\n            SSLContext sslContext = SSLContext.getInstance(\"TLS\");\n            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(\n                    TrustManagerFactory.getDefaultAlgorithm());\n            trustManagerFactory.init(trusted);\n            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);\n            return sslContext.getSocketFactory();\n        } catch (Exception e) {\n            Log.e(\"MyApp\", e.getMessage(), e);\n        }\n        return null;\n    }\n\n    public void makeRequest() {\n        try {\n            OkHttpClient client = new OkHttpClient();\n            client.setSslSocketFactory(getPinnedCertSslSocketFactory(context));\n\n            Request request = new Request.Builder()\n                    .url(ENDPOINT)\n                    .build();\n\n            Response response = client.newCall(request).execute();\n\n            Log.d(\"MyApp\", response.body().string());\n\n        } catch (Exception e) {\n            Log.e(\"MyApp\", e.getMessage(), e);\n\n        }\n    }\n}\n<\/code><\/pre>\n<p>As you can see we instantiate a new instance of <code>OkHttpClient<\/code> and call <code>setSslSocketFactory<\/code>, passing in a <code>SSLSocketFactory<\/code> with our custom truststore. Make sure you set <code>TRUST_STORE_PASSWORD<\/code> to the password you passed into the shell script. Your OkHttp instance should now only accept the certificate you specified.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After reading this blog post I was able to modify the concept for use with OkHttp. You should use at least version 2.0 if you want to avoid using a global SSL context. This modification applies only to the current instance of OkHttp, and changes that instance so that it only accepts certificates from the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-7720","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/7720","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=7720"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/7720\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=7720"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=7720"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=7720"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}