代码混淆简介
针对工程源码的混淆可以降低工程被破解攻击的风险,缩短代码的类与成员的名称,减小应用的大小。
DevEco Studio提供代码混淆的能力并默认开启,API 10及以上版本的Stage模型、编译模式为release时自动进行代码混淆。
使用约束
- 仅支持Stage工程
- 编译模式为release
- 模块及模块依赖的HAR均未配置关闭混淆的规则-disable-obfuscation
混淆范围
在应用工程中,代码混淆支持以下格式文件混淆,混淆后的缓存文件保存在模块目录下的build/[...]/release目录下。
- ArkTS文件
- TS文件
- JS文件
开启代码混淆
代码混淆已经被集成了到SDK中,可以在DevEco Studio中很方便地使用。
代码混淆目前只提供名称混淆的能力(因为其它混淆能力会劣化性能)。 开启代码混淆可以混淆以下名称:
- 参数名和局部变量名
- 顶层作用域的名称
- 属性名称
代码混淆默认使能对参数名和局部变量名的混淆。顶层作用域名称和属性名称的混淆是默认关闭的,因为默认打开可能会导致运行时错误。这些混淆功能通过混淆选项来开启它们。
创建一个新工程的时候,配置文件build-profile.json5中会自动生成以下内容:
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": true,
"files": ["./obfuscation-rules.txt"],
}
}
}
创建一个新的library的时候,还会额外生成consumerFiles属性:
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": true,
"files": ["./obfuscation-rules.txt"],
}
"consumerFiles": ["./consumer-rules.txt"]
}
}
混淆功能默认开启,若被关闭希望重新开启混淆需要满足条件: 属性ruleOptions.enable的值为true。
属性ruleOptions.files中指定的混淆配置文件会在构建HAP、HSP或HAR的时候生效。
属性consumerFiles中指定的混淆配置文件会在构建依赖这个library的模块时生效。 这些混淆配置文件的内容还会被合并到HAR包中的obfuscation.txt文件。
当构建HAP、HSP和HAR的时候,最终的混淆规则是当前构建模块的ruleOptions.files属性,依赖library的consumerFiles属性,以及依赖HAR包中的obfuscation.txt文件的合并。
如果构建的是HAR,HAR包中的obfuscation.txt是自身的consumerFiles属性, 依赖library的consumerFiles属性,以及依赖HAR包中的obfuscation.txt文件的合并。构建HAP、HSP不会生成obfuscation.txt。
混淆规则配置文件
在创建工程或library的时候,DevEco Studio会自动生成obfuscation-rules.txt和consumer-rules.txt文件,
但是它们默认不会包含任何混淆规则。混淆规则可以写到这些文件中,或者其它自定义文件,
然后将文件路径放到ruleOptions.files和consumerFiles中,如下面的例子所示。
"buildOption": {
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": true,
"files": ["./obfuscation-rules.txt", "./myrules.txt"], //myrules.txt放入配置文件build-profile.json5同级目录下
}
"consumerFiles": ["./consumer-rules.txt", "./my-consumer-rules.txt"]
}
}
}
配置混淆规则
混淆规则分为两种类型,一种是混淆选项,一种是保留选项;前者是提供顶层作用域名称、属性名称、文件名称等多种混淆功能配置开关,后者是提供各种混淆功能的白名单配置能力。
混淆选项
-disable-obfuscation
关闭所有混淆。如果使用这个选项,那么构建出来的HAP、HSP或HAR将不会被混淆。
-enable-property-obfuscation
开启属性混淆。 如果使用这个选项,那么所有的属性名都会被混淆,除了下面场景:
-
被import/export直接导入或导出的类、对象的属性名不会被混淆。例如下面例子中的属性名data不会被混淆。
export class MyClass { data: string; }
-
ArkUI组件中的属性名不会被混淆。例如下面例子中的message和data不会被混淆。
@Component struct MyExample { @State message: string = "hello"; data: number[] = []; ... }
-
被保留选项指定的属性名不会被混淆。
-
SDK API列表中的属性名不会被混淆。SDK API列表是构建时从SDK中自动提取出来的一个名称列表,其缓存文件为systemApiCache.json,路径为工程目录下build/cache/{...}/release/obfuscation中
-
在Native API场景中,so库对应的d.ts文件中声明的API不会被混淆。
-
字符串字面量属性名不会被混淆。例如下面例子中的"name"和"age"不会被混淆。
let person = {"name": "abc"}; person["age"] = 22;
如果想混淆字符串字面量属性名,需要在该选项的基础上再使用-enable-string-property-obfuscation选项。例如
-enable-property-obfuscation -enable-string-property-obfuscation
注意:
1. 如果代码里面有字符串属性名包含特殊字符(除了a-z, A-Z, 0-9, _之外的字符),例如let obj = {"\n": 123, "": 4, " ": 5},建议不要开启-enable-string-property-obfuscation选项,因为可能无法通过保留选项来指定保留这些名字。
2. SDK API的属性白名单中不包含声明文件中使用的字符串常量值,例如示例中的字符串'ohos.want.action.home'未包含在属性白名单中
// SDK API文件@ohos.app.ability.wantConstant片段: export enum Params { ACTION_HOME = 'ohos.want.action.home' } // 开发者源码示例: let params = obj['ohos.want.action.home'];
因此在开启了-enable-string-property-obfuscation选项时,如果想保留代码中使用的SDK API字符串常量的属性不被混淆,例如obj['ohos.want.action.home'], 那么需要使用keep选项保留。
-enable-toplevel-obfuscation
开启顶层作用域名称混淆。如果使用这个选项,那么所有的顶层作用域的名称都会被混淆,除了下面场景:
- 被import/export的名称不会被混淆。
- 当前文件找不到声明的名称不会被混淆。
- 被保留选项指定的顶层作用域名称不会被混淆。
- SDK API列表中的顶层作用域名称不会被混淆。
-enable-filename-obfuscation
开启文件/文件夹名称混淆。如果使用这个选项,那么所有的文件/文件夹名称都会被混淆,除了下面场景:
- oh-package.json5文件中'main'、'types'字段配置的文件/文件夹名称不会被混淆。
- 模块内module.json5文件中'srcEntry'字段配置的文件/文件夹名称不会被混