2

I want to improve safety of my Android application. I am using OkHttp version 3.

How to:

1) use Certificate Pinning with OkHttp.

2) use Public Key Pinning with OkHttp.

When I am doing this:

httpClient.certificatePinner(new CertificatePinner.Builder()
            .add(BuildConfig.HOST_NAME, "sha256/VRtYBz1boKOAjChfZYssN1AeNZCjywl77l2RTl/v110=")
            .build());

certificate pinning working. But what with Public Key Pinning? How to enable it?

taulus
  • 69
  • 8
  • 3
    https://stackoverflow.com/a/40694369/115145 – CommonsWare Jul 12 '17 at 17:20
  • @CommonsWare is that mean above solution doing both (Certificate and Public Key Pinning) ? – taulus Jul 12 '17 at 17:25
  • 1
    Technically, it is doing public key pinning. Both "certificate pinning" and "public key pinning" have the same basic effect. On Android (both with OkHttp and with Android 7.0's network security configuration), we have been using the term "certificate pinning" for what really is "public key pinning". Personally, I need to do a better job of using the terms properly. I am not aware of any Android solution that implements true certificate pinning. – CommonsWare Jul 12 '17 at 18:08
  • Thanks @CommonsWare for help! – taulus Jul 13 '17 at 06:21
  • 1
    For clarity, OkHttp does not support HPKP (https://en.wikipedia.org/wiki/HTTP_Public_Key_Pinning) via Http response headers. But manual checks including your app grabbing and storing the pins from the response headers for future sessions will work. – Yuri Schimke Jul 13 '17 at 08:05
  • How to generate the SHA-256 of my SSL Certificate? – malhobayyeb Feb 15 '18 at 12:40

1 Answers1

0

certificate pinning working. But what with Public Key Pinning? How to enable it?

Since Android API 24 you can do it for any Http stack via the res/xml/network_security_config.xml file as described in their docs:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config>
        <domain includeSubdomains="true">example.com</domain>
        <pin-set expiration="2018-01-01">
            <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
            <!-- backup pin -->
            <pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin>
        </pin-set>
    </domain-config>
</network-security-config>

This approach is much more easy to implement then previous ones, but still prone to misconfiguration and typos, plus you need to know how to properly create the SHA-256 digest from the public key of the certificate you want to pin.

I recommend you to use the Mobile Certificate Pinning Generator to help you with your certificate pinning implementation. This free online tool will generate for you the SHA-256 digest for the given domains and provide a network_security_config.xml file ready to be copy pasted into your project.

For example, if in your mobile app project you wanted to hypothetically pin against the domain httpbin.org and example.com:

Config tab for the Mobile Certificate pinning Generator web page

The warnings are there because no backup pin was provided and it is a best practice to always provide one by uploading a backup certificate file that is valid for the domain and that is not yet being used live.

Config tab for the Mobile Certificate pinning Generator web page

Now you just need to copy paste the configuration to your project as stated in that same page:

Create the file ./main/res/xml/network_security_config.xml in your project.

Copy the above certificate pinning xml configuration and paste it into the file.

Open your AndroidManifest.xml file and add the following code snippet android:networkSecurityConfig="@xml/network_security_config" inside the application tag.

Rebuild your mobile app and double check you can still make requests to the APIs.

Or you can learn how to do it with the Pin Test App example repo:

This repo provides the basic steps for integrating certificate pinning into your mobile app with the use of this Approov free tool. This guide is written specifically for native Android apps from API 24 (Android 7.0) onwards that you wish to protect the API calls with certificate pinning.

To follow this guide you only need to have an Android development setup on your machine.

NOTE: Never pin against domains you don't control. For example, the ones used by your mobile app to connect with Third Party services. To pin against this domains you need to use a Reverse Proxy. You can learn more about in the article I wrote about Using a Reverse Proxy to Protect Third Party APIs:

In this article you will start by learning what Third Party APIs are, and why you shouldn’t access them directly from within your mobile app. Next you will learn what a Reverse Proxy is, followed by when and why you should use it to protect the access to the Third Party APIs used in your mobile app.

Exadra37
  • 11,244
  • 3
  • 43
  • 57