HarmonyOS Next开发学习手册——代码肴杂

打印 上一主题 下一主题

主题 1620|帖子 1620|积分 4860

代码肴杂简介

针对工程源码的肴杂可以低落工程被破解攻击的风险,缩短代码的类与成员的名称,减小应用的巨细。
DevEco Studio提供代码肴杂的能力并默认开启,API 10及以上版本的Stage模子、 编译模式为release 时自动进行代码肴杂。
使用约束



  • 仅支持Stage工程
  • 编译模式为release
  • 模块及模块依赖的HAR均未配置关闭肴杂的规则-disable-obfuscation
肴杂范围

在应用工程中,代码肴杂支持以下格式文件肴杂,肴杂后的缓存文件保存在模块目录下的build/[…]/release目录下。


  • ArkTS文件
  • TS文件
  • JS文件
开启代码肴杂

代码肴杂已经被集成了到SDK中,可以在DevEco Studio中很方便地使用。
代码肴杂目前只提供名称肴杂的能力(由于其它肴杂能力会劣化性能)。 开启代码肴杂可以肴杂以下名称:


  • 参数名和局部变量名
  • 顶层作用域的名称
  • 属性名称
代码肴杂默认使能对参数名和局部变量名的肴杂。顶层作用域名称和属性名称的肴杂是默认关闭的,由于默认打开大概会导致运行时错误。这些肴杂功能通过肴杂选项来开启它们。
创建一个新工程的时候,配置文件build-profile.json5中会自动生成以下内容:
  1. "arkOptions": {
  2.   "obfuscation": {
  3.     "ruleOptions": {
  4.       "enable": true,
  5.       "files": ["./obfuscation-rules.txt"],
  6.     }
  7.   }
  8. }
复制代码
创建一个新的library的时候,还会额外生成consumerFiles属性:
  1. "arkOptions": {
  2.   "obfuscation": {
  3.     "ruleOptions": {
  4.       "enable": true,
  5.       "files": ["./obfuscation-rules.txt"],
  6.     }
  7.     "consumerFiles": ["./consumer-rules.txt"]
  8.   }
  9. }
复制代码
肴杂功能默认开启,若被关闭盼望重新开启肴杂必要满意条件: 属性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中,如下面的例子所示。
  1. "buildOption": {
  2.   "arkOptions": {
  3.     "obfuscation": {
  4.       "ruleOptions": {
  5.         "enable": true,
  6.         "files": ["./obfuscation-rules.txt", "./myrules.txt"], //myrules.txt放入配置文件build-profile.json5同级目录下
  7.       }
  8.       "consumerFiles": ["./consumer-rules.txt", "./my-consumer-rules.txt"]
  9.     }
  10.   }
  11. }
复制代码
配置肴杂规则

肴杂规则分为两种类型,一种是 肴杂选项 ,一种是 保存选项 ;前者是提供顶层作用域名称、属性名称、文件名称等多种肴杂功能配置开关,后者是提供各种肴杂功能的白名单配置能力。
肴杂选项

-disable-obfuscation
关闭全部肴杂。假如使用这个选项,那么构建出来的HAP、HSP或HAR将不会被肴杂。
-enable-property-obfuscation
开启属性肴杂。 假如使用这个选项,那么全部的属性名都会被肴杂,除了下面场景:


  • 被import/export直接导入或导出的类、对象的属性名不会被肴杂。例如下面例子中的属性名data不会被肴杂。
  1. export class MyClass {
  2.    data: string;
  3. }
复制代码


  • ArkUI组件中的属性名不会被肴杂。例如下面例子中的message和data不会被肴杂。
  1. @Component struct MyExample {
  2.     @State message: string = "hello";
  3.     data: number[] = [];
  4.     ...
  5. }
复制代码


  • 被 保存选项 指定的属性名不会被肴杂。
  • SDK API列表中的属性名不会被肴杂。SDK API列表是构建时从SDK中自动提取出来的一个名称列表,其缓存文件为systemApiCache.json,路径为工程目录下build/cache/{…}/release/obfuscation中
  • 在Native API场景中,so库对应的d.ts文件中声明的API不会被肴杂。
  • 字符串字面量属性名不会被肴杂。例如下面例子中的"name"和"age"不会被肴杂。
  1. let person = {"name": "abc"};
  2. person["age"] = 22;
复制代码
假如想肴杂字符串字面量属性名,必要在该选项的根本上再使用-enable-string-property-obfuscation选项。例如
  1. -enable-property-obfuscation
  2. -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’未包罗在属性白名单中
  1. // SDK API文件@ohos.app.ability.wantConstant片段:
  2. export enum Params {
  3.   ACTION_HOME = 'ohos.want.action.home'
  4. }
  5. // 开发者源码示例:
  6. 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’字段配置的文件/文件夹名称不会被肴杂。
  • 被 -keep-file-name 指定的文件/文件夹名称不会被肴杂。
  • 非ECMAScript模块引用方式(ECMAScript模块示例:import {foo} from ‘./filename’)
  • 非路径引用方式,例如例子中的json5不会被肴杂 import module from ‘json5’
注意
由于系统会在应用运行时加载某些指定的文件,针对这类文件,开发者必要手动在[-keep-file-name]选项中配置相应的白名单,防止指定文件被肴杂,导致运行失败。
上述必要手动配置白名单的环境,包罗但不限于以了局景:


  • 当模块中包罗Ability组件时。用户必要将src/main/module.json5中,'abilities’字段下全部’srcEntry’对应的路径配置到白名单中。
  • 当模块中包罗Worker多线程服务时,用户必要将build-profiles.json5中,‘buildOption’-‘sourceOption’-'workers’字段下全部的路径配置到白名单中。
-enable-export-obfuscation
开启直接导入或导出的类或对象的名称和属性名肴杂。假如使用这个选项,那么模块中的直接导入或导出的名称都会被肴杂,除了下面场景:


  • 远程HAR(真实路径在oh_modules中的包)中导出的类或对象的名称和属性名不会被肴杂。
  • 被 保存选项 指定的名称与属性名不会被肴杂。
  • SDK API列表中的名称不会被肴杂。
注意

  • 肴杂导入或导出的类中属性名称必要同时开启-enable-property-obfuscation与-enable-export-obfuscation选项。
  • 编译HSP时,假如开启-enable-export-obfuscation选项,必要在模块中的肴杂配置文件obfuscation-rules.txt中保存对外暴露的接口。
  • HAP/HSP/HAR依赖HSP场景下,编译时假如开启-enable-export-obfuscation选项,必要在模块中的肴杂配置文件obfuscation-rules.txt中保存HSP导入的接口。
  1. // 代码示例(HSP中入口文件Index.ets):
  2. export { add, customApiName } from './src/main/ets/utils/Calc'
  3. // 保留接口名称配置示例:
  4. // HSP以及依赖此HSP的模块中obfuscation-rules.txt文件配置:
  5. keep-global-name
  6. add
  7. customApiName
复制代码
-compact
去除不必要的空格符和全部的换行符。假如使用这个选项,那么全部代码会被压缩到一行。
注意
release模式构建的应用栈信息仅包罗代码行号,不包罗列号,因此compact功能开启后无法依据报错栈中的行号定位到源码详细位置。
-remove-log
删除以了局景中对 console.*语句的调用,要求console.*语句返回值未被调用。

  • 文件顶层的调用
  • 代码块Block中的调用
  • 模块Module中的调用
  • switch语句中的调用
-print-namecache filepath
将名称缓存保存到指定的文件路径。名称缓存包罗名称肴杂前后的映射。
注意
每次全量构建工程时都会生成新的namecache.json文件,因此您每次发布新版本时都要注意保存一个该文件的副本。
-apply-namecache filepath
复用指定的名称缓存文件。名字将会被肴杂成缓存映射对应的名字,假如没有对应,将会被肴杂成新的随机段名字。
该选项应该在增量编译场景中被使用。
默认环境下,DevEco Studio会在暂时的缓存目录中保存缓存文件,而且在增量编译场景中自动应用该缓存文件。
缓存目录:build/cache/{…}/release/obfuscation
-remove-comments
删除文件中的全部解释,包罗单行、多行,及JsDoc解释。以了局景除外:
声明文件中,在-keep-comments中配置的类、方法、struct、罗列等名称上方的JsDoc解释。
注意
编译生成的源码文件中的解释默认会被全部删除,不支持配置保存。
保存选项

-keep-property-name [,identifiers,…]
指定想保存的属性名,支持使用名称类通配符。例如下面的例子:
  1. -keep-property-name
  2. age
  3. firstName
  4. lastName
复制代码
注意
该选项在开启-enable-property-obfuscation时生效
哪些属性名应该被保存?
为了保障肴杂的精确性,建议保存全部不通过点语法访问的属性。
例子:
  1. var obj = {x0: 0, x1: 0, x2: 0};
  2. for (var i = 0; i <= 2; i++) {
  3.     console.log(obj['x' + i]);  // x0, x1, x2 应该被保留
  4. }
  5. Object.defineProperty(obj, 'y', {});  // y 应该被保留
  6. console.log(obj.y);
  7. obj.s = 0;
  8. let key = 's';
  9. console.log(obj[key]);        // s 应该被保留
  10. obj.u = 0;
  11. console.log(obj.u);           // u 可以被正确地混淆
  12. obj.t = 0;
  13. console.log(obj['t']);        // 在开启字符串字面量属性名混淆时t和't'会被正确地混淆,但是建议保留
  14. obj['v'] = 0;
  15. console.log(obj['v']);        // 在开启字符串字面量属性名混淆时'v'会被正确地混淆,但是建议保留
复制代码
对于间接导出的场景,例如export MyClass和let a = MyClass; export {a};,假如不想肴杂它们的属性名,那么必要使用 保存选项 来保存这些属性名。另外,对于直接导出的类或对象的属性的属性名,例如下面例子中的name和age, 假如不想肴杂它们,那么也必要使用 保存选项 来保存这些属性名。
  1. export class MyClass {
  2.     person = {name: "123", age: 100};
  3. }
复制代码
没有在so库的d.ts文件中声明的API(例如示例中的foo),假如要在ArkTS/TS/JS文件中使用需手动保存API名称。
  1. import testNapi from 'library.so'
  2. testNapi.foo()
复制代码
-keep-global-name [,identifiers,…]
指定要保存的顶层作用域的名称,支持使用名称类通配符。例如,
  1. -keep-global-name
  2. Person
  3. printPersonName
复制代码
哪些顶层作用域的名称应该被保存?
在Javascript中全局变量是globalThis的属性。假如在代码中使用globalThis去访问全局变量,那么该变量名应该被保存。
示例:
  1. var a = 0;
  2. console.log(globalThis.a);  // a 应该被保留
  3. function foo(){}
  4. globalThis.foo();           // foo 应该被保留
  5. var c = 0;
  6. console.log(c);             // c 可以被正确地混淆
  7. function bar(){}
  8. bar();                      // bar 可以被正确地混淆
  9. class MyClass {}
  10. let d = new MyClass();      // MyClass 可以被正确地混淆
复制代码
-keep-file-name [,identifiers,…]
指定要保存的文件/文件夹的名称(不必要写文件后缀),支持使用名称类通配符。例如,
  1. -keep-file-name
  2. index
  3. entry
复制代码
哪些文件名应该被保存?
  1. const module1 = require('./file1')   // ArkTS不支持CommonJS语法,这种路径引用应该被保留
  2. const moduleName = './file2'
  3. const module2 = import(moduleName)    // 动态引用方式无法识别moduleName是否是路径,应该被保留
复制代码
-keep-comments [,identifiers,…]
保存声明文件中元素上方的JsDoc解释,支持使用名称类通配符。例如想保存声明文件中Human类上方的JsDoc解释,可进行以下配置:
  1. -keep-comments
  2. Human
复制代码
注意

  • 该选项在开启-remove-comments时生效
  • 当声明文件中某个元素名称被肴杂时,该元素上方的JsDoc解释无法通过-keep-comments保存。例如当在-keep-comments中配置了exportClass时,假如下面的类名被肴杂,其JsDoc解释无法被保存:
  1. /*
  2. * @class exportClass
  3. */
  4. export class exportClass {}
复制代码
-keep-dts filepath
保存指定路径的.d.ts文件中的名称。这里的文件路径可以是一个目录,这种环境下目录中全部.d.ts文件中的名称都会被保存。
假如在构建HAR时使用了这个选项,那么文件中的名称会被归并到最后的obfuscation.txt文件中。
-keep path
保存指定路径中的全部名称(例如变量名、类名、属性名等)不被肴杂。这个路径可以是文件与文件夹,若是文件夹,则文件夹下的文件及子文件夹中文件都不肴杂。
路径仅支持相对路径,./与…/为相对于肴杂配置文件地点目录,支持使用路径类通配符。
  1. -keep
  2. ./src/main/ets/fileName.ts   // fileName.ts中的名称不混淆
  3. ../folder                    // folder目录下文件及子文件夹中的名称都不混淆
  4. ../oh_modules/json5          // 引用的三方库json5里所有文件中的名称都不混淆
复制代码
注:该功能不影响文件名肴杂-enable-filename-obfuscation的功能
保存选项支持的通配符
名称类通配符
名称类通配符使用方式如下:
通配符含义示例?匹配恣意单个字符"AB?“能匹配"ABC"等,但不能匹配"AB”*匹配恣意数量的恣意字符“AB"能匹配"AB”、“aABb”、“cAB”、"ABc"等 使用示例
保存全部以a开头的属性名称:
  1. -keep-property-name
  2. a*
复制代码
保存全部单个字符的属性名称:
  1. -keep-property-name
  2. ?
复制代码
保存全部属性名称:
  1. -keep-property-name
  2. *
复制代码
路径类通配符
路径类通配符使用方式如下:
通配符含义示例?匹配恣意单个字符,除了路径分隔符/“…/a?“能匹配”…/ab"等,但不能匹配”…/a/"*匹配恣意数量的恣意字符,除了路径分隔符/“…/a*/c"能匹配”…/ab/c",但不能匹配"…/ab/d/s/c"**匹配恣意数量的恣意字符“…/a**/c"能匹配”…/ab/c",也能匹配"…/ab/d/s/c"!表示非,只能写在某个路径最前端,用来扫除用户配置的白名单中已有的某种环境“!../a/b/c.ets"表示除”…/a/b/c.ets"以外 使用示例
表示路径…/a/b/中全部文件夹(不包罗子文件夹)中的c.ets文件不会被肴杂:
  1. -keep
  2. ../a/b/*/c.ets
复制代码
表示路径…/a/b/中全部文件夹(包罗子文件夹)中的c.ets文件不会被肴杂:
  1. -keep
  2. ../a/b/
  3. !../a/b/c.ets
复制代码
表示路径…/a/b/中,除了c.ets文件以外的其它文件都不会被肴杂。此中,!不可单独使用,只能用来扫除白名单中已有的环境:
  1. -keep
  2. ../a/b/
  3. !../a/b/c.ets
复制代码
表示路径…/a/中的全部文件(不包罗子文件夹)不会被肴杂:
  1. -keep
  2. ../a/*
复制代码
表示路径…/a/下的全部文件夹(包罗子文件夹)中的全部文件不会被肴杂:
  1. -keep
  2. ../a/*
  3. *
复制代码
表示模块内的全部文件不会被肴杂:
  1. -keep
  2. ./**
复制代码
注意
(1)以上选项,不支持配置通配符*、?、!作其它含义使用。
例如:
  1. class A {  '*'= 1}-keep-property-name
  2. *
复制代码
此时表示匹配恣意数量的恣意字符,配置效果为全部属性名称都不肴杂,而不是只有属性不被肴杂。
(2)-keep选项中只允许使用/路径格式,不支持\或\。
解释

可以使用#在肴杂规则文件中进行解释。每行以#开头的文本会被当做是解释,例如下面的例子:
  1. # white list for MainAbility.ets
  2. -keep-global-name
  3. MyComponent
  4. GlobalFunction
  5. -keep-property-name # white list for dynamic property names
  6. firstName
  7. lastName
  8. age
复制代码
构建HAR时,解释不会被归并到最后的obfuscation.txt文件中。
肴杂规则归并计谋

一个工程中常常会有许多肴杂规则文件,这些文件来自于:


  • 主工程的ruleOptions.files (这里主工程指的是正在构建的工程)
  • 当地依赖的library中的consumerFiles选项中指定的文件
  • 远程依赖的HAR包中的obfuscate.txt文件
当构建主工程的时候,这些文件中的肴杂规则会按照下面的归并计谋(伪代码)进行归并:
  1. let `listRules` 表示上面提到的所有混淆规则文件的列表
  2. let finalRule = {
  3.     disableObfuscation: false,
  4.     enablePropertyObfuscation: false,
  5.     enableToplevelObfuscation: false,
  6.     compact: false,
  7.     removeLog: false,
  8.     keepPropertyName: [],
  9.     keepGlobalName: [],
  10.     keepDts: [],
  11.     printNamecache: string,
  12.     applyNamecache: string
  13. }
  14. for each file in `listRules`:
  15.     for each option in file:
  16.         switch(option) {
  17.             case -disable-obfuscation:
  18.                 finalRule.disableObfuscation = true;
  19.                 continue;
  20.             case -enable-property-obfuscation:
  21.                 finalRule.enablePropertyObfuscation = true;
  22.                 continue;
  23.             case -enable-toplevel-obfuscation:
  24.                 finalRule.enableToplevelObfuscation = true;
  25.                 continue;
  26.             case -compact:
  27.                 finalRule.compact = true;
  28.                 continue;
  29.             case -remove-log:
  30.                 finalRule.removeLog = true;
  31.                 continue;
  32.             case -print-namecache:
  33.                 finalRule.printNamecache = #{指定的路径名};
  34.                 continue;
  35.             case -apply-namecache:
  36.                 finalRule.applyNamecache = #{指定的路径名};
  37.                 continue;
  38.             case -keep-property-name:
  39.                 finalRule.keepPropertyName.push(#{指定的名称});
  40.                 continue;
  41.             case -keep-global-name:
  42.                 finalRule.keepGlobalName.push(#{指定的名称});
  43.                 continue;
  44.             case -keep-dts:
  45.                 finalRule.keepDts.push(#{指定的路径});
  46.                 continue;
  47.         }
  48.     end-for
  49. end-for
复制代码
最后使用的肴杂规则来自于对象finalRule。
假如构建的是HAR,那么终极的obfuscate.txt文件内容来自于主工程和当地依赖的library的consumerFiles选项,
以及依赖的HAR的obfuscate.txt文件的归并。归并计谋和上面一样,除了以下的不同:


  • -keep-dts选项会被转换成-keep-global-name和-keep-property-name。
  • -print-namecache和apply-namecache选项会被忽略,不会出如今最后的obfuscate.txt文件中。
报错栈还原

经过肴杂的应用程序中代码名称会发生更改,crash时打印的报错栈更难以理解,由于报错栈与源码不完全一致。开发职员可使用DevEco Studio命令工具Command Line Tools中的hstack插件来还原源码堆栈。
阐明



  • 目前不支持在hvigor构建流程中插入自界说肴杂插件
  • 肴杂的HAR包被模块依赖,若模块开启肴杂,则HAR包会被二次肴杂
  • DevEco Studio右上角Product选项,将此中Build Mode选择release,可开启release编译模式

鸿蒙全栈开发全新学习指南

为了积极培养鸿蒙生态人才,让各人都能学习到鸿蒙开发最新的技术,针对一些在职职员、0根本小白、应届生/盘算机专业、鸿蒙爱好者等人群,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线【包罗了大厂APP实战项目开发
本路线共分为四个阶段:

第一阶段:鸿蒙初中级开发必备技能


第二阶段:鸿蒙南北双向高工技能根本:gitee.com/MNxiaona/733GH


第三阶段:应用开发中高级就业技术


第四阶段:全网首发-工业级南向装备开发就业技术:gitee.com/MNxiaona/733GH


鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH


写在最后



  • 假如你觉得这篇内容对你还蛮有资助,我想约请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

涛声依旧在

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表