/

React Native Integration

ByteHide Shield provides special support for React Native applications, allowing you to protect your JavaScript code from reverse engineering and unauthorized access. This guide explains how to install and use the Shield React Native plugin.

Installation

Install the ByteHide Shield React Native plugin from npm:

npm install --save-dev @bytehide/react-native-shield

Or with yarn:

yarn add --dev @bytehide/react-native-shield

Integration Methods

There are several ways to integrate Shield with your React Native project. Choose the method that best fits your workflow:

Method 1: Using a Standalone Script

Create a script file in the root of your project (e.g., obfuscate.js) and add the following code:

// obfuscate.js
const shield = require('@bytehide/react-native-shield');

const distDir = './dist';                    // Path to your bundle directory
const projectToken = 'your-project-token';   // Your ByteHide project token
const replace = true;                        // Whether to replace original files
const excludePatterns = [];                  // Patterns to exclude from obfuscation
const obfuscatedExtension = '.obf';          // Extension for obfuscated files

shield
  .obfuscate(distDir, projectToken, replace, excludePatterns, obfuscatedExtension)
  .then(() => console.log('Obfuscation completed successfully!'))
  .catch((err) => console.error('Error during obfuscation:', err));

Run the script manually:

node obfuscate.js

Method 2: Adding to package.json Scripts

Add the obfuscation step as a script in your project's package.json:

// package.json
{
  "scripts": {
    "build": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output ./dist/index.android.bundle --assets-dest ./dist",
    "obfuscate": "node obfuscate.js",
    "build:protected": "npm run build && npm run obfuscate"
  }
}

Then you can run:

npm run build:protected

Method 3: Integration into Build Processes

For Android (build.gradle)

Add a custom task to android/app/build.gradle:

// android/app/build.gradle
task obfuscateJs(type: Exec) {
    commandLine "node", "${project.rootDir}/../obfuscate.js"
}

preBuild.dependsOn obfuscateJs

For iOS (Run Script in Xcode)

  1. Open your project in Xcode
  2. Select your target and go to Build Phases
  3. Click "+" and select "New Run Script Phase"
  4. Add the following script:
node "$SRCROOT/../obfuscate.js"

Method 4: Using CLI Commands

You can use the CLI command directly:

npx @bytehide/react-native-shield obfuscate \
  --src ./dist \
  --projectToken your-project-token \
  --replace true \
  --exclude "*.test.js,*.spec.js" \
  --obfuscatedExtension .obf

Configuration Options

The React Native Shield plugin accepts the following options:

OptionTypeDefaultDescription
src / distDirstringRequiredPath to the directory containing files to be protected
projectTokenstringRequiredYour ByteHide project token
replacebooleanfalseWhether to replace original files with obfuscated versions
excludestring''Comma-separated list of glob patterns to exclude
obfuscatedExtensionstring'.obf'File extension for obfuscated files (when replace is false)

React Native-Specific Considerations

When protecting React Native applications, consider the following best practices:

Performance Impact

Obfuscation can affect the startup time and runtime performance of React Native apps. To minimize this impact:

  • Exclude files that don't need protection (e.g., UI components, styles)
  • Apply lighter protection settings to performance-critical code
  • Test thoroughly on low-end devices to ensure acceptable performance

Hermes Compatibility

If you're using Hermes (React Native's JavaScript engine):

  • Test your obfuscated code thoroughly with Hermes enabled
  • Some advanced obfuscation techniques may not be compatible with Hermes
  • Consider using the target: 'hermes' option if available in your configuration

Bundle Size

Obfuscation can increase bundle size. To minimize this:

  • Use the compact option to reduce whitespace
  • Be selective with protection options that add significant overhead
  • Consider using Shield only for production builds

Advanced Configuration

You can customize the protection settings by adding a configuration file:

// shield.config.js
module.exports = {
  controlFlowFlattening: true,
  controlFlowFlatteningThreshold: 0.5,
  stringArray: true,
  stringArrayEncoding: ['base64'],
  selfDefending: false,
  identifierNamesGenerator: 'hexadecimal',
  compact: true,
  target: 'browser', // or 'node' depending on your build setup
  
  // React Native specific exclusions
  reservedNames: [
    '^React$',
    '^Component$',
    '^useState$',
    '^useEffect$',
    '^StyleSheet$',
    '^Animated$',
  ],
  
  // Exclude common React Native patterns
  reservedStrings: [
    'react-native',
    'ReactNative',
    '^StyleSheet.create$'
  ]
};

Then reference this in your obfuscation script:

// obfuscate.js
const shield = require('@bytehide/react-native-shield');
const config = require('./shield.config.js');

shield
  .obfuscate('./dist', 'your-project-token', true, [], '.obf', config)
  .then(() => console.log('Obfuscation completed successfully!'))
  .catch((err) => console.error('Error during obfuscation:', err));

Custom React Native CLI Integration

You can create a custom React Native CLI command by adding a react-native.config.js file:

// react-native.config.js
module.exports = {
  commands: [
    {
      name: 'obfuscate',
      func: () => {
        const shield = require('@bytehide/react-native-shield');
        const distDir = './dist';
        const projectToken = process.env.BYTEHIDE_PROJECT_TOKEN || 'your-project-token';
        
        shield
          .obfuscate(distDir, projectToken, true)
          .then(() => console.log('Obfuscation completed successfully!'))
          .catch((err) => console.error('Error during obfuscation:', err));
      },
    },
  ],
};

Then run it with:

npx react-native obfuscate

Complete Example Workflow

Here's a complete workflow for integrating Shield into a React Native project:

  1. Install the plugin
npm install --save-dev @bytehide/react-native-shield
  1. Create a configuration file
// shield.config.js
module.exports = {
  controlFlowFlattening: true,
  stringArray: true,
  stringArrayEncoding: ['base64'],
  deadCodeInjection: false,
  selfDefending: false,
  compact: true,
  target: 'browser',
  reservedNames: [
    '^React$', '^Component$', '^useState$', '^useEffect$'
  ]
};
  1. Create an obfuscation script
// obfuscate.js
const shield = require('@bytehide/react-native-shield');
const config = require('./shield.config.js');

const isProd = process.env.NODE_ENV === 'production';
const projectToken = process.env.BYTEHIDE_PROJECT_TOKEN;

if (!projectToken) {
  console.error('Error: BYTEHIDE_PROJECT_TOKEN environment variable is required');
  process.exit(1);
}

// Apply more aggressive protection in production
if (isProd) {
  config.deadCodeInjection = true;
  config.selfDefending = true;
}

shield
  .obfuscate('./dist', projectToken, true, ['*.map'], '', config)
  .then(() => console.log('Obfuscation completed successfully!'))
  .catch((err) => console.error('Error during obfuscation:', err));
  1. Add scripts to package.json
{
  "scripts": {
    "build:android": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output ./dist/index.android.bundle --assets-dest ./dist",
    "build:ios": "react-native bundle --platform ios --dev false --entry-file index.js --bundle-output ./dist/main.jsbundle --assets-dest ./dist",
    "obfuscate": "cross-env NODE_ENV=production node obfuscate.js",
    "build:protected:android": "npm run build:android && npm run obfuscate",
    "build:protected:ios": "npm run build:ios && npm run obfuscate"
  }
}
  1. Configure CI/CD

For GitHub Actions:

# .github/workflows/build.yml
name: Build Protected App

on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v2
    - name: Set up Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '16'
    
    - name: Install dependencies
      run: npm ci
      
    - name: Build and protect Android bundle
      run: npm run build:protected:android
      env:
        BYTEHIDE_PROJECT_TOKEN: ${{ secrets.BYTEHIDE_PROJECT_TOKEN }}

Troubleshooting

Common Issues

Obfuscation Errors

If you encounter errors during obfuscation:

  • Check that you're using the correct project token
  • Ensure your bundle is properly generated before obfuscation
  • Try excluding problematic files using the exclude option

App Crashes After Obfuscation

If your app crashes after obfuscation:

  • Start with lighter protection settings and gradually increase
  • Add more items to reservedNames and reservedStrings to preserve critical code
  • Test with different levels of protection to find the right balance

Next Steps

Previous
Rollup