Code Monkey home page Code Monkey logo

react-native-cert-pinner's Introduction

react-native-cert-pinner

This package is now ARCHIVED. Approov users should use instead the Approov React Native quickstart, while non Approov users can use the Approov free tool: Mobile Certificate Pinning Generator.

IMPORTANT: This repository relates to Approov 1 and has not been updated to reflect the new features and usage for the latest version of Approov. Contact the Approov support If you were using this package with Approov 1 and you need help to migrate to the latest Approov version.

This package manages TLS certificate pinning in react-native for Android and iOS.

Getting started

$ npm install react-native-cert-pinner --save

Mostly automatic installation

$ react-native link react-native-cert-pinner

Manual installation

iOS

Add the following line to the project targets in your Podfile:

pod 'TrustKit', '~> 1.4.2'

Then run pod install.

Android

  1. Open up android/app/src/main/java/[...]/MainApplication.java
  • Add import com.criticalblue.reactnative.CertPinnerPackage; to the imports at the top of the file
  • Add new CertPinnerPackage() to the list returned by the getPackages() method
  1. Append the following lines to android/settings.gradle:
    include ':react-native-cert-pinner'
    project(':react-native-cert-pinner').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-cert-pinner/android')
    
  2. Insert the following lines inside the dependencies block in android/app/build.gradle:
      compile project(':react-native-cert-pinner')
    

Usage

To use the react-native networking utilities, like fetch(), certificate pinning must be done in the native app before the app's react-native javascript is run.

Unlike typical installed packages, there is no need to require any modules in the javascript. Everything is setup and enforced inside the native module.

Certificate Pinning Configuration

A pinset utility is provided to help configure the native modules for pinning.

The default setup assumes you are running in your project's home directory. The default configuration file is ./pinset.json, and the default native android project is assumed to be located at ./android. Both these locations may be overriden on the command line.

Command Help

To get help:

$ npx pinset -h

    pinset [command] [options]

      init ..... initialize pinset configuration
      gen ...... generate pinset configuration
      version .. show package version
      help ..... show help menu for a command

or for a sub-command:

$ npx pinset help gen

    pinset gen [options] [config]

      --android, -a <path> .. path to Android project (defaults to './android')
      --ios, -i <path> ...... path to iOS project (defaults to './ios')
      --force, -f ........... always overwrite existing configuration

      config ................ configuration file - defaults to 'pinset.json'

Initialization

The first step is to generate a starter configuration:

$ npx pinset init

This command will not overwrite an existing configuration file unless the --force flag is used.

Lookup

Next, determine which URLs you want to pin, and determine each certificate's public key hash. A convenient utility is provided by Report URI at https://report-uri.com/home/pkp_hash. Enter a URL to see the current chain of certificate hashes.

Enter the desired public key hashes into the pinset.json file:

{
  "domains": {
    "*.approov.io": {
      "pins": [
        "sha256/0000000000000000000000000000000000000000000",
        "sha256/1111111111111111111111111111111111111111111"
      ]
    },
    "*.criticalblue.com": {
      "pins": [
        "sha256/2222222222222222222222222222222222222222222",
        "sha256/3333333333333333333333333333333333333333333"
      ]
    }
  }
}

Domains starting with*. will include all subdomains.

It is recommended to select multiple hashes with at least one of them being from an intermediate certificate.

Generation

Once the configuration is set, generate the native project sources:

$ npx pinset gen
Reading config file './pinset.json'.
Updating java file './android/app/src/main/java/com/criticalblue/reactnative/GeneratedCertificatePinner.java'.
Updating plist file './ios/example/info.plist'.

Build and run the react-native app, for example:

$ react-native run-ios

Updates

To update the certificate pins, edit the configuration file, regenerate the native sources, and rebuild the app.

Note, there is no way to update the pin sets from javascript while the app is running.

Certificate Security

If you consider publishing hashes of public key certificates to be a security breach, you may want to remove or ignore the pinset configuration and generated fines from your repository.

To ignore the default files in a git repository, add to .gitignore:

# default configuration file
./pinset.json

# default generated android source
./android/app/src/main/java/com/criticalblue/reactnative/GeneratedCertificatePinner.java
./ios/<your project here>/info.plist

Future Enhancements

  • Automatically regenerate native source files whenever the pin set configuration changes.
  • Add source regeneration and git ignores to the mostly automatic react-native linking step.
  • Add certificate lookup to the pinset utility.
  • Better secure pinset information within the app.

react-native-cert-pinner's People

Contributors

exadra37 avatar ma-pe avatar sfstpala avatar skiph avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-cert-pinner's Issues

Can not get response when debug mode is off

I've checked my sha256 from SSLLabs website it show 3 certificates. [The first one is Certificate #1: RSA 4096 bits (SHA256withRSA)]

I've used a PinSHA256 from certificate #1 and #2.
But when debug mode is off the app can not get response from api.

Could you please guide me how to check the incorrect spot?

Erro to execute npx pinset get - in generated 'GeneratedCertificatePinner.java'

Hello, I am trying to run the 'gen' command but this error is occurring, what can it be? Have you seen anything like that?

"react": "16.5.0",
"react-native": "0.57.0"
"react-native-cert-pinner": "^0.4.1"

Updating java file './android/app/src/main/java/com/criticalblue/reactnative/GeneratedCertificatePinner.java'. Java file './android/app/src/main/java/com/criticalblue/reactnative/GeneratedCertificatePinner.java' error: Error: ENOENT: no such file or directory, open './android/app/src/main/java/com/criticalblue/reactnative/GeneratedCertificatePinner.java'

Timeline: iOS Support

Hey there,

thank you very much for releasing this library. This is really massive for me, because you can use the react-native fetch library which supports blobs.

Do you have any timeline for the iOS support in mind. We are looking forward to release our app for android and ios soon and I'd be more than happy to help by any means.

Greetings
Malte

multiple server pinning

Is there a way to enable multiple server certificates for api use?

builder.add("*.example.com", "sha256/KEY_GOES_HERE");
builder.add("*.another.com", "sha256/KEY_GOES_HERE");

but it wont get work and throwing error not allowed. is there any solution for this?
can someone plz help?

Axios

I use axios redux-axios-middleware packages in my project I developed. Can I use it with this package? Is it mandatory to use fetch?

Not working with proguard

Hi, first of all kudos for the great work.
I'd like to discuss about an issue I'm having with this package.
In order to make it work with proguard I had to exclude the package from obfuscation with:

-keep class com.criticalblue.reactnative.** {
*;
}

Since the package is using reflection to access the certPinner:

try {
            Class noparams[] = {};
            Class clazz = Class.forName("com.criticalblue.reactnative.GeneratedCertificatePinner");
            Method method = clazz.getDeclaredMethod("instance", noparams);
            certificatePinner = (CertificatePinner) method.invoke(null);
            Log.i(TAG, "Generated Certficate Pinner in use");
        } catch(Exception e){
            Log.e(TAG, "No Generated Certficate Pinner found - likely a pinset configuration error");
            Log.w(TAG, "CERTIFICATE PINNING NOT BEING USED");
        }

But excluding this package from obfuscation makes it extremely trivial for an attacker to decompile and bypass the pinning feature.
Wouldn't it be better to manually import the com.criticalblue.reactnative.GeneratedCertificatePinner package inside of CertPinnerPackage.java and invoke the static instance method instead of relying on reflection?
This would improve Proguard obfuscation without breaking the functionality.
Thank you,

Francesco

Pod Install Dependency Issue

Using RN 0.60.4, I receive the following error after attempting to run pod install within the ios folder of my project:

Detected React Native module pods for CertPinner, RCTRestart, RNCAsyncStorage, RNDeviceInfo, RNFS, RNGestureHandler, RNLocalize, RNSVG, RNSha256, RNVectorIcons, ReactNativeExceptionHandler, react-native-background-timer, react-native-biometrics, react-native-blur, react-native-config, react-native-netinfo, and react-native-webview
Detected React Native module pods for CertPinner, RCTRestart, RNCAsyncStorage, RNDeviceInfo, RNFS, RNGestureHandler, RNLocalize, RNSVG, RNSha256, RNVectorIcons, ReactNativeExceptionHandler, react-native-background-timer, react-native-biometrics, react-native-blur, react-native-config, react-native-netinfo, and react-native-webview
Analyzing dependencies
[!] There are multiple dependencies with different sources for `CertPinner` in `Podfile`:

- CertPinner (from `../node_modules/react-native-cert-pinner/ios`)
- CertPinner (from `../node_modules/react-native-cert-pinner`)

it appears the same CertPinner dependency is required twice? Also note that I used automatic linking during installation. Thanks in advance for any guidance.

Project still alive?

In the README.md there is noted that this repo will be upgraded to Approov version 2 'soon'. That was since posted in August 2019. Are there still plans to do that, or more to the point, is this project still being maintained? @skiph @Exadra37 @sfstpala @ma-pe

Android pinning not working

As the title says, I'm having trouble getting Android based SSL pinning to be enforced.

I followed the instructions to manually link and the app compiles correctly, however, no pinning seems to get enforced even when I use pins for other websites and my requests load just as they did before.

Is there a way to debug why this wouldn't be working?

My generated pinner java class using reddit's SSL hash (Please note, mydomain.com is just for the purposes of this paste)

package com.criticalblue.reactnative;

import okhttp3.CertificatePinner;

public class GeneratedCertificatePinner {
    public static CertificatePinner instance() {
        CertificatePinner.Builder builder = new CertificatePinner.Builder();

        builder.add("*.mydomain.com", "sha256/ekcBV69V+nWj2avgL3Ko6YUQ2OTGIWWcTMs14g7JsMc=");
        builder.add("*.mydomain.com", "sha256/5kJvNEMw0KjrCAu7eXY5HZdvyCS13BbA0VJG1RSP91w=");

        return builder.build();
    }
}

Unable to run npx pinset gen

Getting following error:
Java file './android/app/src/main/java/com/criticalblue/reactnative/GeneratedCertificatePinner.java' error: Error: ENOENT: no such file or directory, open './android/app/src/main/java/com/criticalblue/reactnative/GeneratedCertificatePinner.java'

Unable to find "criticalblue" package inside './android/app/src/main/java/com'.

Because of this, In IOS Info.plist is not getting updated too. (by npx pinset gen)

Have tried both manual and automatic linking.

Unknown issue about TrustKit configuration

Hi,

I followed the installation and usage guide carefully step by step both on iOS and on Android.

I have initialized and configured the pinset.json then I have successfully generated the pinset native codes.

In particular on iOS I am able to compile and run the app, however, at the moment of App launch, I get following error on Xcode:

Screenshot 2020-06-17 at 09 38 09

So I checked the info.plist file and the react-native-cert-pinner generated fields, checked the domains and the relative hashes (each domain has at least two hashes) and all seems to be fine:

Screenshot 2020-06-17 at 09 47 06

What could be wrong?

Always getting accept when fetch data

Thank you about this package!, I'm trying to fetch data with some different pins and all the time i get the data even when the pins is incorrect, i did all the process that mention in the Getting started and the usage (exactly the same).
I tried your example project and it doesn't work too(some time goes to catch and some times not...).
any advise or maybe there is a problem in the last update of the package..?

I use react native 59.8

Edit-
It's so weird i tried to run the example folder with some pins randomly and there some pins that return "hello world" and some Error..

Fetch is successfull with wrong pins

I have installed the module as described and configured my pins with a given domain. Now if I set wrong pins for the domain and generate the pinset then rebuild the app, my calls to the domain are still successfull. Am I missing anything?

Here is my configuration :

Environment:
  OS: macOS 10.14.1
  Node: 9.11.2
  Yarn: 1.10.1
  npm: 6.4.1
  Watchman: 4.9.0
  Xcode: Xcode 10.1 Build version 10B61
  Android Studio: 3.1 AI-173.4907809

Packages: (wanted => installed)
  react: 16.3.1 => 16.3.1
  react-native: 0.55.3 => 0.55.3

Pubblish the latest version to NPM

The version on the master branch is updated and it is working with the latest version of React Native (PR #7 solved the podspec issue). The version that is published on NPM registry is not updated and it fails when you run "pod install".

Please pubblish the latest version on NPM

Thanks

Distinguish a failed pin

Thank you for open sourcing this great library.

If I use the fetch api to request an api, and the request fails due to failed ssl-pinning, i catch a
TypeError: Network request failed

If I use fetch to request an api while I am offline, I will also get a
TypeError: Network request failed

How to distinguish between these two. I need the user to know wether he is offline or he is in a "maybe compromised" network.

Greetings
Malte

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.