Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Obfuscate entire React Native app including JavaScript code

How to obfuscate my react-native JS code? I have set the following in my build.gradle file:

release {       minifyEnabled true       proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"  } 

Here is my proguard-rules.pro file (default):

# Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see #   http://developer.android.com/guide/developing/tools/proguard.html  # Add any project specific keep options here:  # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { #   public *; #} 

But still after unzipping the apk I can find my JS components name, variables and url's

like image 260
artsnr Avatar asked Oct 08 '18 07:10

artsnr


People also ask

Is it possible to obfuscate JavaScript?

JavaScript obfuscation is a series of code transformations that turn plain, easy-to-read JS code into a modified version that is extremely hard to understand and reverse-engineer. Unlike encryption, where you must supply a password used for decryption, there's no decryption key in JavaScript obfuscation.

Can you obfuscate obfuscated code?

Obfuscation means to make something difficult to understand. Programming code is often obfuscated to protect intellectual property or trade secrets, and to prevent an attacker from reverse engineering a proprietary software program. Encrypting some or all of a program's code is one obfuscation method.


2 Answers

As your React Native JavaScript code is built upon native code for Android and iOS, an entire obfuscation process would consider all three codebases:

Obfuscate Java code for Android

Fortunately your project already includes the Proguard obfuscator, which can be enabled as following:

  1. Update your release configuration in the build.gradle file located in android/app/ folder:

    def enableProguardInReleaseBuilds = true  android {     // other config omitted for brevity     buildTypes {         release {             debuggable false             shrinkResources enableProguardInReleaseBuilds             zipAlignEnabled enableProguardInReleaseBuilds             minifyEnabled enableProguardInReleaseBuilds             useProguard enableProguardInReleaseBuilds             setProguardFiles([getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'])         }     } } 
  2. Enable ProGuard obfuscation and edit rules accordingly in proguard-rules.pro file located in android/app/ folder.

    The following line of code needs to be commented out (add # at beginning of line):

    #-dontobfuscate 

    At this stage building the release version of your Android app should contain obfuscated Java code. Check it by analysing your APK, where you should find function calls such as a, b instead of the their actual names.

Code above referenced from Maria Korlotian's Medium post. Check also latest default React Native ProGuard configuration from GitHub repository.

From Android 3.3 beta onwards, a more optimised obfuscator called R8 can be used.

Obfuscate Objective-C code for iOS

There is no built-in library in the iOS project that will obfuscate your code, therefore an external package has to be used. PPiOS-Rename and ObjC-Obfuscator are two options here. The detailed documentation can be found in their GitHub repositories.

Obfuscate JavaScript code

This would be the most important part of the obfuscation as the our actual code is written in JavaScript. The react-native-obfuscating-transformer npm package can be used here:

  1. Add the package to your project

    npm install react-native-obfuscating-transformer 
  2. Add / update the CLI configuration in rn-cli.config.js at the root of your project, where android and ios folders reside.

    module.exports = {  getTransformModulePath() {    return require.resolve("./transformer")  }, } 

    Create this file if it does not exist yet.

  3. Create the transformer.js file also at the root and specify configuration options as appropriate:

    const obfuscatingTransformer = require("react-native-obfuscating-transformer");  module.exports = obfuscatingTransformer({     /* Insert here any required configuration */ }); 

    Pay attention especially to the scope of the obfuscation process, which by default targets only files in src/ folder (node_modules is excluded by default).


Having all the above stated, obfuscating your app will not make it inherently secured – although security and obscurity can be better than only the former, there are many other security enhancements (if not requirements) that can be implemented in a React Native app. This includes storing sensitive information in secure storage (Keystore in Android / Keychain in iOS), implementing certificate pinning if appropriate, and others.

Other useful links:

  • Secure Storage in React Native by Randy Coulman

  • Strengthen TLS in React Native through Certificate Pinning by Skip Hovsmith

like image 129
Siavas Avatar answered Oct 31 '22 19:10

Siavas


The above answer by @Siavas covered most of the things however the metro plugin react-native-obfuscating-transformer doesn't seems to be obfuscating the index.android.bundle, you can try obfuscator-io-metro-plugin this seems to be working fine. it is also based on javascript-obfuscator.

you need to include the following config in metro.config.js

const jsoMetroPlugin = require("obfuscator-io-metro-plugin")(   {     // these option are obfuscation options from javascript-obfuscator     compact: false,     sourceMap: true,     controlFlowFlattening: true,     controlFlowFlatteningThreshold: 1,     numbersToExpressions: true,     simplify: true,     shuffleStringArray: true,     splitStrings: true,     stringArrayThreshold: 1,   },   {     runInDev: false /* optional */,     logObfuscatedFiles: true /* optional generated files will be located at ./.jso */,   } );   module.exports = {   transformer: {     getTransformOptions: async () => ({       transform: {         experimentalImportSupport: false,         inlineRequires: false,       },     }),   },   ...jsoMetroPlugin, }; 
like image 25
shubham jha Avatar answered Oct 31 '22 19:10

shubham jha