白盒加密SDK的目的是帮助客户端低成本接入高标准的安全保护机制,免受恶意安全攻击,从而集中精力建设业务本身。

话不多说,我们今天来看看Android可以如何接入白盒加密SDK。

环境需求

条目说明
兼容平台Android 4.0+
开发环境Android Studio 3.0.1 或者 Eclipse + ADT
CPU架构ARM 或者 x86
SDK三方依赖

SDK接入

1.SDK获取

1)访问顶象技术官网,注册账号
2)登录, 进入控制台,访问“全流程端防控->白盒加密SDK”模块
3)新增App,填写相关信息
)下载对应平台SDK

2.SDK文件结构

  • SDK目录结构
  • assets Android 资源文件
  • dx-whitebox-${version}.jar Android jar包
  • armeabi, armeabi-v7a, arm64-v8a, x86 4个abi平台的动态库文件

Android Studio 集成

点击下载Demo

想直接运行demo项目的话,请跑gradle命令assembleRelease

1.Android Studio导入jar, so

  • 将dx-whitebox-x.x.x.jar, so文件放到相应模块的libs目录下
  • 将assets中资源文件放到相应项目assets目录下
  • 没有assets目录的,在Android Studio对应app目录下新建Assets Folder

2.build.gradle 配置

android{
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

    packagingOptions {
        doNotStrip "**/libDX*.so"
    }

}
repositories{
        flatDir{
              dirs 'libs'
      }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}

3.混淆配置

-dontwarn *.com.dingxiang.mobile.**
-dontwarn *.com.mobile.strenc.**
-keep class com.dingxiang.mobile.whitebox.**{*;}
-keep class com.security.inner.**{*;}
-keep class *.com.dingxiang.mobile.**{*;}
-keep class *.com.mobile.strenc.**{*;}

React Native 方式集成

点击下载Demo

1.React Native 环境配置

具体参考facebook官方文档: https://facebook.github.io/react-native/docs/getting-started

2.集成SDK

通过官方react-native init {project_name}命令,可生成Android Studio项目,其目录在:ReactNative根目录的android目录下

Android Studio项目如何集成SDK,请参考 前文 Android Studio 集成

3.引入React Native库

build.gradle下:

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
    implementation "com.facebook.react:react-native:+"  // From node_modules
}

4.添加React Native Android代码

  • 创建 ReactContextBaseJavaModule 实现类
    此类是RN和Android交互的桥接类。 如需JS调用Android方法,必须在方法前添加ReactMethod注释,如下面startDemoTest方法。
public class DXModule extends ReactContextBaseJavaModule {

    public DXModule(ReactApplicationContext reactContext) {
        mContext = reactContext;
    }

    @Override
    public String getName() {
        return "DXModule";
    }

    @ReactMethod
    public void startDemoTest(int param1, final Callback callback){
        // 调用SDK的地方,具体例子请查看Demo
    }

    ...
}
  • 创建 ReactPackage 实现类
    其中createNativeModules方法要返回DXModule的实例
public class DXPackage implements ReactPackage {

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new DXModule(reactContext));
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}
  • 创建 ReactApplication 实现类
    其中getPackages方法要返回DXPackage的实例
public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
              new MainReactPackage()
              , new DXPackage()
      );
    }

    @Override
    protected String getJSMainModuleName() {
      return "index";
    }
  };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
      super.onCreate();
      SoLoader.init(this, /* native exopackage */ false);
  }
}
  • 创建 ReactActivity 实现类
    其中DXWhiteboxRNDemo就是ReactNative 需要注册的入口
public class MainActivity extends ReactActivity {

    /**
     * Returns the name of the main component registered from JavaScript.
     * This is used to schedule rendering of the component.
     */
    @Override
    protected String getMainComponentName() {
        return "DXWhiteboxRNDemo";
    }
}

5.AndroidManifest 配置

<uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:allowBackup="false"
      android:theme="@style/AppTheme">
      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
        android:windowSoftInputMode="adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
      </activity>
      <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    </application>

6.React Native调用Android代码

  • 注册Android模块 修改文件 {RactNative_pro}/app.json:
{
  "name": "DXWhiteboxRNDemo",
  "displayName": "DXWhiteboxRNDemo"
}
  • 修改JS主界面 修改文件 {RactNative_pro}/App.js:
import React, {Component} from 'react';
import {Button, DeviceEventEmitter, NativeModules, View} from 'react-native';

export default class NativeInteractionDemo extends Component {
    // 注册监听
    componentDidMount() {
        this.subscription = DeviceEventEmitter.addListener('DXEvent', function (msg) {
            alert(msg)
        });
    }

    componentWillUnmount() {
        this.subscription.remove();
    }

    render() {
        return <View>
            <Button
                onPress={() => {
                    this.startDemo();
                    this.showToast();
                }
                }
                title="开始Demo"
            />
        </View>
    }

    // 调用安卓原生代码并回传数据
    startDemo() {
        NativeModules.DXModule.startDemoTest(1, (status, msg) => {
                console.log('status:' + status + ' ' + msg);
            }
        );
    }

    // 调用原生安卓土司
    showToast() {
        NativeModules.DXModule.showToast("正在执行测试...")
    }
}

7.运行Android项目

ReactNative目录下,执行命令
react-native run-android

DXWhiteBox类说明

在调用功能方法之前必须调用初始化方法

1.SDK初始化

/**
 * @description SDK全局初始化,一般放在应用启动处调用,如Application.onCreate里。
 * 调用setup()方法后,会在当前app内启用:内存保护、调试器监测、设备root监测、
 * 代码注入监测、代码hook监测、Android模拟器检测、Android app多开监测等运行时安全检测。
 *
 * @param context Android上下文
 * @return 初始化是否成功
 */
public static boolean DXWhiteBox.setup(Context context);

2.数据加密/解密

/**
 * @description 加密
 * @param key 指定加密方式:k0~k9。具体说明请看“k0~k9使用说明”
 * @param input 待加密数据
 * @return 加密后的数据
 */
public static byte[] encrypt(String key, byte[] input);

/**
 * @description 解密
 * @param key 指定解密方式:k0~k9。具体说明请看“k0~k9使用说明”
 * @param input 待解密数据
 * @return 解密后的数据
 */
public static byte[] decrypt(String key, byte[] input);

/**
 * @description 无key加密,内部随机
 * @param input 待加密数据
 * @return 加密后的数据
 */
public static byte[] encrypt( byte[] input);

/**
 * @description 无key解密,内部随机
 * @param input 待解密数据
 * @return 解密后的数据
 */
public static byte[] decrypt( byte[] input);

3.文件加密/解密

/**
 * @description 解密方式读取文件
 * @param key 指定解密方式:目前允许的key为k0, k4, k5, k6, k9。具体说明请看“k0~k9说明”
 * @param filePath 文件路径
 * @return 文件内容
 * @throws IOException
 */
public static byte[] readFile(String key, String filePath) throws IOException


/**
 * @description 加密方式写文件
 * @param key 指定加密方式:目前允许的key为k0, k4, k5, k6, k9。具体说明请看“k0~k9说明”
 * @param data 写入数据
 * @param filePath 目标文件路径
 * @throws IOException
 */
public static void writeFile(String key, byte[] data, String filePath) throws IOException

4.加签/验证

/**
 * @description 加签数据
 * @param key 加签方式,k0 ~ k9。具体说明请看“k0~k9使用说明”
 * @param input 加签数据
 * @return 加签输出数据
 */
public static String sign(String key, byte[] input);


/**
 * @description 验签
 * @param key 验签方式,k0 ~ k9。具体说明请看“k0~k9使用说明”
 * @param input 验签数据
 * @param sig 加签值
 * @return 验签是否成功
 */
public static boolean verify(String key, byte[] input, String sig);

/**
 * @description 随机加签,不需要指定加签方式
 * @param input 待加签数据
 * @return 加签数据
 */
public static String sign( byte[] input);

/**
 * @description 随机验签,不需要指定加签方式
 * @param input 待验签数据
 * @param sig 加签值
 * @return 验签是否成功
 */
public static boolean verify(byte[] input, String sig);

以上就是整个白盒加密SDK的流程,如有不足之处,请多指教~


小飞象
80 声望5 粉丝