1# ArkGuard
2
3## Overview
4
5Source code obfuscation helps reduce the risk of application hacking as well as the application package size by shortening class names and member names.
6
7>**NOTE**
8>
9> 1. In versions earlier than DevEco Studio 5.0.3.600, code obfuscation is enabled by default for a new project. It automatically obfuscates the code of the stage model of API10 or later. This operation applies only to code compiled in [release mode](#usage-description), and obfuscation is limited to parameter names and local variable names.
10> 2. In DevEco Studio 5.0.3.600 and later versions, code obfuscation is disabled by default when you create a project. To enable code obfuscation, set the ruleOptions.enable field in the build-profile.json5 file of the module to true. In addition, the obfuscation-rules.txt configuration file enables four recommended obfuscation options by default: -enable-property-obfuscation, -enable-toplevel-obfuscation, -enable-filename-obfuscation, and -enable-export-obfuscation. You can modify the obfuscation configuration as required. Note that enabling the four rules may cause the app to crash during running. Therefore, you are advised to rectify the app functions by referring to [Troubleshooting](#troubleshooting).
11
12### Constraints
13
14* Only the projects developed on the stage model are supported.
15* The build mode of the project is release.
16* The **disable-obfuscation** option is not configured for the module and the HAR on which the module depends.
17
18### Code Obfuscation Scope
19
20In a project, the following files can be obfuscated, and the cache files after obfuscation are stored in **build/[...]/release** in the module directory.
21
22* ArkTS files
23* TS files
24* JS files
25
26## Enabling Code Obfuscation
27
28Code obfuscation has been integrated into the system and can be enabled for use in DevEco Studio.
29
30Currently, only name obfuscation is provided. Other obfuscation capabilities deteriorate performance. You can use code obfuscation to obfuscate the following names:
31
32* Parameter names and local variable names
33* Top-level scope names
34* Property names
35* Exported names
36* File names
37
38After code obfuscation is enabled, parameter names and local variable names will be obfuscated by default. No option needs to be configured. Obfuscation of top-level scope name, property names, exported names, and file names may cause runtime errors. You can enable or disable these obfuscation capabilities by configuring obfuscate options.
39
40When a module is created, the following content is automatically generated in the module-level build-profile.json5 file:
41
42```
43"arkOptions": {
44  "obfuscation": {
45    "ruleOptions": {
46      "enable": true,
47      "files": ["./obfuscation-rules.txt"],
48    }
49  }
50}
51```
52
53When a library is created, the **consumerFiles** field is automatically generated in addition to the preceding content.
54
55```
56"arkOptions": {
57  "obfuscation": {
58    "ruleOptions": {
59      "enable": true,
60      "files": ["./obfuscation-rules.txt"],
61    }
62    "consumerFiles": ["./consumer-rules.txt"]
63  }
64}
65```
66
67If you disable code obfuscation and then want to enable it again, the value of **ruleOptions.enable** must be **true**.
68
69The obfuscation configuration files specified in the **ruleOptions.files** field take effect when the HAP, HSP, or HAR is built.
70The obfuscation configuration files specified in the **consumerFiles** field take effect when the module that depends on the library is built. The contents of these obfuscation configuration files are also merged into the **obfuscation.txt** file in the HAR.
71
72During the build of the HAP, HSP, or HAR, the final obfuscation rules are the combination of the **ruleOptions.files** field of the current module, the **consumerFiles** field of the dependent library, and the **obfuscation.txt** file in the dependent HAR.
73During HAR build, the **obfuscation.txt** file in the HAR contains the combination of the **consumerFiles** field of the current HAR, the **consumerFiles** field of the dependent library, and the **obfuscation.txt** file in the dependent HAR. No **obfuscation.txt** file is generated during HAP or HSP build. For details about the merge policy, see [Obfuscation Rule Merge Policy](#obfuscation-rule-merge-policy).
74
75### Obfuscation Rule Configuration File
76
77During the creation of a project or library, DevEco Studio automatically generates the **obfuscation-rules.txt** and **consumer-rules.txt** files. You can write obfuscation rules into these files or other user-defined files, and then add the file paths in **ruleOptions.files** and **consumerFiles**, as shown in the following example.
78
79```
80"buildOption": {
81  "arkOptions": {
82    "obfuscation": {
83      "ruleOptions": {
84        "enable": true,
85        "files": ["./obfuscation-rules.txt", "./myrules.txt"], // Place myrules.txt in the same directory as the build-profile.json5 file.
86      }
87      "consumerFiles": ["./consumer-rules.txt", "./my-consumer-rules.txt"]
88    }
89  }
90}
91```
92
93## Configuring Obfuscation Rules
94
95There are two types of obfuscation rules: [obfuscate options](#obfuscate-options) and [keep options](#keep-options). The former provides a switch for multiple obfuscation capabilities, such as obfuscation of top-level scope names, property names, and file names. The latter provides the trustlist configuration of various obfuscation capabilities.
96
97**NOTE**
98
99Any modification to the obfuscation configuration takes effect only after a full build of the application.
100
101### Obfuscate Options
102
103#### -disable-obfuscation
104
105Disables code obfuscation. If this option is used, the built HAP, HSP, or HAR is not obfuscated.
106
107#### -enable-property-obfuscation
108
109Enables property obfuscation. If this option is used, all property names except the following are obfuscated:
110
111* Property names of classes and objects that are directly imported or exported by using the **import** or **export** statement. For example, the property name **data** in the following example is not obfuscated.
112
113    ```
114    export class MyClass {
115       data: string;
116    }
117    ```
118
119* Property names in ArkUI components. For example, **message** and **data** in the following example are not obfuscated.
120
121    ```
122    @Component struct MyExample {
123        @State message: string = "hello";
124        data: number[] = [];
125        ...
126    }
127    ```
128
129* Property names specified by [keep options](#keep-options).
130* Property names in the SDK API list. The SDK API list is a name set automatically extracted from the SDK during build. The cache file is **systemApiCache.json**, which is stored in **build/default/cache/{...}/release/obfuscation** in the project directory.
131* String literal property names. For example, **"name"** and **"age"** in the following example are not obfuscated.
132
133    ```
134    let person = {"name": "abc"};
135    person["age"] = 22;
136    ```
137
138    If you want to obfuscate the string literal property name, use the **-enable-string-property-obfuscation** option in addition to the current option, as follows:
139
140    ```
141    -enable-property-obfuscation
142    -enable-string-property-obfuscation
143    ```
144
145    **NOTE**
146
147    **1.** If a string literal property name in the code contains special characters, for example, **let obj = {"\n": 123, "": 4, " ": 5}**, you are advised not to use the **-enable-string-property-obfuscation** option because these names may fail to be kept using [keep options](#keep-options). Special characters refer to characters other than lowercase letters a-z, uppercase letters A-Z, digits 0-9, and underscores (_).
148    **2.** The property trustlist of the SDK API list does not contain the string constants used in the declaration file. For example, the string **'ohos.want.action.home'** in the example is not included in the property trustlist.
149
150    ```
151    // Part of the SDK API file @ohos.app.ability.wantConstant:
152    export enum Params {
153      ACTION_HOME = 'ohos.want.action.home'
154    }
155    // Source code example:
156    let params = obj['ohos.want.action.home'];
157    ```
158
159    When the **-enable-string-property-obfuscation** option is used, use the keep option if you want to keep the property names of the SDK API string constants used in the source code, for example, **obj['ohos.want.action.home']**.
160
161#### -enable-toplevel-obfuscation
162
163Enables top-level scope name obfuscation. If this option is used, all names of all top-level scopes except the following are obfuscated:
164
165* Top-level scope names imported or exported using the **import** or **export** statement.
166* Top-level scope names that are not declared in the current file.
167* Top-level scope names specified by [keep options](#keep-options).
168* Top-level scope names in the SDK API list.
169
170#### -enable-filename-obfuscation
171
172Enables file or folder name obfuscation. If this option is used, all file/folder names will be confused. For example:
173
174```
175// Both directory and filename are confused.
176import func from '../directory/filename';
177import { foo } from '../directory/filename';
178const module = import('../directory/filename');
179```
180
181In addition to the following scenarios:
182
183* File or folder names specified by the **main** and **types** fields in the **oh-package.json5** file.
184* File or folder names specified by the **srcEntry** field in the **module.json5** file of the module.
185* File or folder names specified by [-keep-file-name](#keep-options).
186* File or folder names in non-ECMAScript module reference mode. An ECMAScript module example is **import {foo} from './filename'**.
187* File or folder names in non-path reference mode. For example, **json5** in the example **import module from 'json5'** is not obfuscated.
188
189**NOTE**
190
191The system loads certain files during application running. For these files, manually configure a trustlist in the [`-keep-file-name`] option to prevent them from being obfuscated. Otherwise, the application may fail to run.
192In the following scenarios, you need to manually configure a trustlist:
193
194* The module contains an ability component. In this case, add all paths configured for **srcEntry** under the **abilities** field in **src/main/module.json5** to the trustlist.
195* The module contains the multithreading service: Worker. In this case, add all paths under the **buildOption'-'sourceOption'-'workers'** field in **build-profiles.json5** to the trustlist.
196
197**Reminder**
198
199The names of the compilation entry file, ability component file, and worker multithreaded file cannot be obfuscated and have been automatically added to the trustlist in DevEco Studio 5.0.3.500. No manual configuration is required. For other files that cannot be obfuscated, you need to manually configure their names in the trustlist.
200
201#### -enable-export-obfuscation
202
203Enables obfuscation for names of classes or objects that are directly imported or exported and their property names. If this option is used, the names directly imported or exported in the module are obfuscated, except the following:
204
205* Names of classes or objects exported from remote HARs (packages whose real paths are in oh_modules) and their property names.
206* Names and property names specified by [keep options](#keep-options).
207* Names in the SDK API list.
208
209**NOTE**
210
2111. To obfuscate property names in imported or exported classes, use both the **-enable-property-obfuscation** and **-enable-export-obfuscation** options.
2122. If the **-enable-export-obfuscation** option is used during HSP build, the externally exposed interfaces must be kept in the **obfuscation-rules.txt** file of the module.
2133. During the build of an HAP, an HSP, and an HSP-dependent HAR, if the **-enable-export-obfuscation** option is used, the interfaces imported from the HSP must be kept in the **obfuscation-rules.txt** file in the module.
214
215    ```
216    // Code example (entry file Index.ets in the HSP):
217    export { add, customApiName } from './src/main/ets/utils/Calc'
218
219    // Example of keeping an interface name:
220    // Configuration of the obfuscation-rules.txt file in the HSP and modules that depend on the HSP:
221    -keep-global-name
222    add
223    customApiName
224    ```
225
226#### -compact
227
228Removes unnecessary spaces and all line feeds. If this option is used, all code is compressed to one line.
229
230**NOTE**
231
232The stack information built in release mode contains the line number of code, but not the column number. Therefore, when the **compact** option is used, the source code cannot be located based on the line number in the stack information.
233
234#### -remove-log
235
236Removes the expressions involving direct calls to the **console.** statement in the following scenarios:
237
2381. Calls at the top layer of a file.
2392. Calls within a code block.
2403. Calls within a module.
2414. Calls within a switch statement.
242
243#### -print-namecache *filepath*
244
245Saves the name cache to the specified file path. The name cache contains mappings before and after name obfuscation.
246
247**NOTE**
248
249A new **namecache.json** file is generated each time the module if fully built. Save a copy of the file each time you publish a new version.
250
251#### -apply-namecache *filepath*
252
253Reuses the specified name cache file. The names will be obfuscated according to the cache mappings. If there is no corresponding name, a new random segment name is used.
254This option should be used in incremental build scenarios.
255
256By default, DevEco Studio saves cache files in a temporary cache directory and automatically applies the cache files during incremental build.
257Cache Directory: **build/default/cache/{...}/release/obfuscation**
258
259#### -remove-comments
260
261Removes JsDoc comments from the declaration file generated after compilation.
262
263**NOTE**
264
265By default, all comments in the source code file generated after the build are removed and cannot be kept.
266You can configure **keep-comments** to keep the JsDoc comments in the declaration file from being obfuscated.
267
268#### -print-kept-names *filepath*
269
270Prints the keep-name list and full trustlist. The **filepath** parameter is optional.
271
272If the **filepath** parameter is not specified, the keep-name list (**keptNames.json**) and full trustlist (**whitelist.json**) are output to the cache directory **build/default/cache/{...}/release/obfuscation** by default.
273
274If the **filepath** parameter is specified, the keep-name list is also exported to the path specified by this parameter. The file path specified must be a relative path, which starts from the directory where the obfuscation configuration file is currently located. The file name extension in the file path must be .json.
275
276The full trustlist (**whitelist.json**) contains all trustlists collected during module compilation. It is classified into the following types:
277
278(1) 'sdk': system APIs.
279
280(2) 'lang': keywords in the language.
281
282(3) 'conf': trustlist in the user-defined keep options.
283
284(4) 'struct': properties in ArkUI structs.
285
286(5) 'export': names and properties exported.
287
288(6) 'strProp': string properties.
289
290(7) 'enum': indicates a member in the enum.
291
292The **keptNames.json** file contains the names that are not obfuscated and the reasons why they are not obfuscated. There are seven reasons: The name is the same as that in the SDK trustlist, language trustlist, user-defined trustlist, struct trustlist, exported name trustlist, or string property trustlist (when string property obfuscation is disabled), or enum trustlist (during HAR module compilation).
293
294**NOTE**
295
2961. When the har module is compiled and attribute obfuscation is enabled, the'enum' whitelist collects the member names in the enum.
297
298Example:
299
300```
301enum Test {
302  member1,
303  member2
304}
305```
306
307The enum whitelist content is ['member1', 'member2']. This is because the compilation intermediate product of the HAR module in earlier versions is a JS file. In the JS file, the enum type is converted into an immediate execution function, and the enum member is converted into a string attribute and a string constant. Therefore, to ensure that the function is normal when attribute obfuscation is enabled, you need to collect the enum member names as a whitelist. This feature is retained when the new bytecode har module is compiled.
308
3092. When the hap/hsp/bytecode har module is compiled and attribute obfuscation is enabled, the'enum' whitelist collects the variable names contained in the initialization expression when the members of enum are initialized.
310
311Example:
312
313```
314let outdoor = 1;
315enum Test {
316  member1,
317  member2 = outdoor + member1 + 2
318}
319```
320
321When the hap/hsp module is compiled, content of the enum whitelist is ['outdoor', 'member1']. When the bytecode har module is compiled, content of the enum whitelist is ['outdoor', 'member1', 'member2'].
322
323### Keep Options
324
325#### -keep-property-name *[,identifiers,...]*
326
327Keeps the specified property names from being obfuscated. Name wildcards are supported. An example is as follows.
328
329```
330-keep-property-name
331age
332firstName
333lastName
334```
335
336> **NOTE**
337>
338> - This option takes effect when **-enable-property-obfuscation** is used.
339>
340> - The attribute whitelist takes effect globally. That is, if multiple attributes with the same name exist in the code, they will not be confused as long as they are the same as those in the whitelist configured in -keep-property-name.
341
342What property names should be kept?
343
344For safety, you are advised to keep all properties that are not accessed through dot notation.
345
346Example:
347
348```
349var obj = {x0: 0, x1: 0, x2: 0};
350for (var i = 0; i <= 2; i++) {
351    console.log(obj['x' + i]); // x0, x1, and x2 should be kept.
352}
353
354Object.defineProperty(obj, 'y', {}); // y should be kept.
355console.info(obj.y);
356
357obj.s = 0;
358let key = 's';
359console.log(obj[key]);        // s should be kept.
360
361obj.u = 0;
362console.log(obj.u);           // u can be correctly obfuscated.
363
364obj.t = 0;
365console.log(obj['t']);        // When obfuscation of string literal property names is enabled, both t and 't' can be correctly obfuscated. However, it is recommended that 't' be kept.
366
367obj['v'] = 0;
368console.log(obj['v']);        // When obfuscation of string literal property names is enabled, 'v' can be correctly obfuscated. However, it is recommended that 'v' be kept.
369```
370
371In the case of indirect exports, for example, **export MyClass** and **let a = MyClass; export {a}**, if you do not want to obfuscate property names, use [keep options](#keep-options) to keep them. For property names of directly exported classes or objects, such as **name** and **age** in the following example, if you do not want to obfuscate them, use [keep options](#keep-options) to keep them.
372
373```
374export class MyClass {
375    person = {name: "123", age: 100};
376}
377```
378
379If an API (for example, **foo** in the example) of the .so library needs to be used in the ArkTS/TS/JS file, manually keep the API name.
380
381```
382import testNapi from 'library.so'
383testNapi.foo() // foo should be kept. Example: -keep-property-name foo
384```
385
386Manually keep the fields used in JSON files.
387
388```
389const jsonData = ('./1.json')
390let jsonStr = JSON.parse(jsonData)
391let jsonObj = jsonStr.jsonProperty // jsonProperty should be kept.
392```
393
394Manually keep database-related fields.
395
396```
397const dataToInsert = {
398  value1: 'example1',   // value1 should be kept.
399};
400```
401
402The custom decorator in the source code modifies member variables, member methods, and parameters, and the intermediate product of the source code compilation is a JS file (for example, the HAR of the release source code is compiled or the source code contains @ts-ignore and @ts-nocheck). The names of the member variables or member methods where these decorators are located need to be retained. This is because when the advanced TS syntax feature is converted to the standard JS syntax, the member variable or member method name of the preceding decorator is hard-coded into a string constant.
403
404Example:
405
406```
407class A {
408  // 1. Member variable decorator
409  @CustomDecoarter
410  The propetyName: string = "" // propetyName needs to be reserved.
411  // 2. Member method decorator
412  @MethodDecoarter
413  methodName1 () {} // methodName1 needs to be reserved.
414  // 3. Method parameter decorator.
415  The methodName2(@ParamDecorator param: string): void { // methodName2 needs to be reserved.
416  }
417}
418```
419
420#### -keep-global-name *[,identifiers,...]*
421
422Keep the top-level scope names from being obfuscated. Name wildcards are supported. Example:
423
424```
425-keep-global-name
426Person
427printPersonName
428```
429
430The names exported from the namespace can also be retained using -keep-global-name.
431
432```
433export namespace Ns {
434  export const age = 18; // -keep-global-name age: reserved variable age
435  export function myFunc () {}; // -keep-global-name myFunc: reserved function myFunc
436}
437```
438
439> **NOTE**
440>
441> The whitelist specified by -keep-global-name takes effect globally. That is, if multiple top-level scope names or export names exist in the code, they will not be confused as long as they are the same as the whitelist names configured in -keep-global-name.
442
443What top-level scope names should be kept?
444
445In JavaScript, variables in the top-level scope are properties of **globalThis**. If **globalThis** is used to access a global variable in the code, the variable name should be kept.
446
447Example:
448
449```
450var a = 0;
451console.log(globalThis.a); // a should be kept.
452
453function foo(){}
454globalThis.foo();           // foo should be kept.
455
456var c = 0;
457console.log(c);             // c can be correctly obfuscated.
458
459function bar(){}
460bar();                      // bar can be correctly obfuscated.
461
462class MyClass {}
463let d = new MyClass();      // MyClass can be correctly obfuscated.
464```
465
466When an API of the SO library is imported by name, if both -enable-toplevel-obfuscation and -enable-export-obfuscation are enabled, you need to manually retain the API name.
467
468```
469import { testNapi, testNapi1 as myNapi } from 'library.so' // testNapi and testNapi1 should be reserved.
470```
471
472#### -keep-file-name *[,identifiers,...]*
473
474Keeps the file or folder names from being obfuscated. You do not need to specify the file name extension. Name wildcards are supported. Example:
475
476```
477-keep-file-name
478index
479entry
480```
481
482What file names should be kept?
483
4841. When the require command is used to introduce a file path, the path should be retained because ArkTS does not support the [CommonJS](../arkts-utils/module-principle.md#commonjs module) syntax.
485
486```
487The const module1 = require('./file1') // file1 should be reserved.
488```
489
4902. In dynamic reference mode, whether the parameter in the import function is a path cannot be identified. Therefore, the path should be reserved in this case.
491
492```
493The const moduleName = './file2' // file2 should be reserved.
494const module2 = import(moduleName)
495```
496
4973. When using [dynamic routing](../ui/arkts-navigation-navigation.md#cross-package-dynamic-routing) for route jump, the path passed to the route should be preserved. Dynamic routing provides system routing tables and custom routing tables. If a custom route table is used for redirection, the method of configuring a whitelist is the same as that in the second dynamic reference scenario. If the system routing table is used for redirection, you need to add the path corresponding to the pageSourceFile field in the resources/base/profile/route_map.json file of the module to the whitelist.
498
499```
500  {
501    "routerMap": [
502      {
503        "name": "PageOne",
504        The "pageSourceFile": "src/main/ets/pages/directory/PageOne.ets", // path must be reserved.
505        "buildFunction": "PageOneBuilder",
506        "data": {
507          "description" : "this is PageOne"
508        }
509      }
510    ]
511  }
512```
513
514#### -keep-comments *[,identifiers,...]*
515
516Keeps the classes, functions, namespaces, enums, structs, interfaces, modules, types, and JsDoc comments above properties in the declaration file generated after compilation from being obfuscated. Name wildcards are supported. For example, to keep the JSDoc comments above the **Human** class in the declaration file, use the following configuration:
517
518```
519-keep-comments
520Human
521```
522
523**NOTE**
524
5251. This option takes effect when **-remove-comments** is used.
5262. If the classes, functions, namespaces, enums, structs, interfaces, modules, types, and property names in the declaration file generated after compilation are confused, the JsDoc comments above the element cannot be kept using **-keep-comments**. For example, when **exportClass** is configured in **-keep-comments**, if the class name is **exportClass** obfuscated, its JSDoc comments cannot be kept:
527
528```
529/*
530 * @class exportClass
531 */
532export class exportClass {}
533```
534
535#### -keep-dts *filepath*
536
537Names (such as variable names, class names, and attribute names) in the .d.ts file of the specified path are added to the -keep-global-name and -keep-property-name whitelists. Note that filepath supports only absolute paths and can be specified as a directory. In this case, the names in all .d.ts files in the directory are retained.
538
539#### -keep *filepath*
540
541Keeps all names (such as variable names, class names, and property names) in the specified relative path from being obfuscated. The path can be a file or directory. If the path is a directory, the files in the directory and subdirectories are not obfuscated.
542The path must be a relative path. **./** and **../** are relative to the directory where the obfuscation configuration file is located. Path wildcards are supported.
543
544```
545-keep
546./src/main/ets/fileName.ts   // Names in the fileName.ts file are not obfuscated.
547../folder                    // Names in all the files under the folder directory and its subdirectories are not obfuscated.
548../oh_modules/json5          // Names in all the files in the imported third-party library json5 are not obfuscated.
549```
550
551**NOTE**
552
5531. For files retained by -keep filepath, the exported names and attributes in the files on the dependent links are retained.
5542. NOTE: This option does not affect the capability provided by the **-enable-filename-obfuscation** option.
555
556#### Wildcards Supported by Keep Options
557
558##### Name Wildcards
559
560The table below lists the name wildcards supported.
561
562| Wildcard| Description                  | Example                                      |
563| ------ | ---------------------- | ------------------------------------------ |
564| ?      | Matches any single character.      | "AB?" matches "ABC", but not "AB".        |
565| \*     | Matches any number of characters.| "\*AB\*" matches "AB", "aABb", "cAB", and "ABc".|
566
567**Use Example**
568
569Keep all property names that start with **a**.
570
571```
572-keep-property-name
573a*
574```
575
576Keep all single-character property names.
577
578```
579-keep-property-name
580?
581```
582
583Keep all property names.
584
585```
586-keep-property-name
587*
588```
589
590##### Path Wildcards
591
592The table below lists the path wildcards supported.
593
594| Wildcard| Description                                                                    | Example                                             |
595| ------ | ------------------------------------------------------------------------ | ------------------------------------------------- |
596| ?     | Matches any single character except the path separator (/).                                     | "../a?" matches "../ab", but not "../a/".        |
597| \*      | Matches any number of characters except the path separator (/).                               | "../a*/c" matches "../ab/c", but not "../ab/d/s/c".|
598| \*\*   | Matches any number of characters.                                                  | "../a**/c" matches "../ab/c" and "../ab/d/s/c". |
599| !      | Negation. It can only be placed at the beginning of a path to exclude a certain case configured in the trustlist.| "!../a/b/c.ets" indicates all paths other than "../a/b/c.ets".          |
600
601**Use Example**
602
603Keep the **c.ets** file in the **../a/b/** directory (excluding subdirectories).
604
605```
606-keep
607../a/b/*/c.ets
608```
609
610Keep the **c.ets** file in the **../a/b/** directory and its subdirectories.
611
612```
613-keep
614../a/b/**/c.ets
615```
616
617Keep all files except the **c.ets** file in the **../a/b/** directory. The exclamation mark (!) cannot be used alone. It can only be used to exclude existing cases in the trustlist.
618
619```
620-keep
621../a/b/
622!../a/b/c.ets
623```
624
625Keep all the files in the **../a/** directory (excluding subdirectories).
626
627```
628-keep
629../a/*
630```
631
632Keep all the files in the **../a/** directory and its subdirectories.
633
634```
635-keep
636../a/**
637```
638
639Keep all the files in the module.
640
641```
642-keep
643./**
644```
645
646**NOTE**
647
648(1) In these options, the wildcards *, ?, and ! cannot be used for other meanings.
649Example:
650
651```
652class A {
653  '*'= 1
654}
655
656-keep-property-name
657*
658```
659
660In this example, * indicates any number of characters, and all property names are kept (not obfuscated). It does not mean that only the * property is kept.
661
662(2) In the **-keep** option, only the path format / is allowed. The path format \ or \\ is not.
663
664### Comments
665
666You can use **#** to comment out an obfuscation rule file. The line that starts with **#** is treated as a comment. Example:
667
668```
669# white list for MainAbility.ets
670-keep-global-name
671MyComponent
672GlobalFunction
673
674-keep-property-name # white list for dynamic property names
675firstName
676lastName
677age
678```
679
680During HAR build, comments are not merged into the final **obfuscation.txt** file.
681
682### Obfuscation Rule Merge Policy
683
684A project often has many obfuscation rule files, which are:
685
686* **ruleOptions.files** of the main project (the project being built)
687* File specified by the **consumerFiles** field in the local dependent libraries
688* **obfuscation.txt** file in remote dependent HARs
689
690When the main project is built, the obfuscation rules in these files are merged according to the following policy (in pseudo code):
691
692```
693let `listRules` indicates the list of all obfuscation rule files mentioned above.
694let finalRule = {
695    disableObfuscation: false,
696    enablePropertyObfuscation: false,
697    enableToplevelObfuscation: false,
698    compact: false,
699    removeLog: false,
700    keepPropertyName: [],
701    keepGlobalName: [],
702    keepDts: [],
703    printNamecache: string,
704    applyNamecache: string
705}
706for each file in `listRules`:
707    for each option in file:
708        switch(option) {
709            case -disable-obfuscation:
710                finalRule.disableObfuscation = true;
711                continue;
712            case -enable-property-obfuscation:
713                finalRule.enablePropertyObfuscation = true;
714                continue;
715            case -enable-toplevel-obfuscation:
716                finalRule.enableToplevelObfuscation = true;
717                continue;
718            case -compact:
719                finalRule.compact = true;
720                continue;
721            case -remove-log:
722                finalRule.removeLog = true;
723                continue;
724            case -print-namecache:
725                finalRule.printNamecache = #{specifiedPathName};
726                continue;
727            case -apply-namecache:
728                finalRule.applyNamecache = #{specifiedPathName};
729                continue;
730            case -keep-property-name:
731                finalRule.keepPropertyName.push(#{specifiedName});
732                continue;
733            case -keep-global-name:
734                finalRule.keepGlobalName.push(#{specifiedName});
735                continue;
736            case -keep-dts:
737                finalRule.keepDts.push(#{specifiedPath});
738                continue;
739        }
740    end-for
741end-for
742```
743
744The final obfuscation rule comes from the object **finalRule**.
745
746If the HAR is built, the final obfuscation.txt file content comes from the consumerFiles option of the HAR and the local dependent library, and the combination of the obfuscation.txt file of the dependent HAR.
747
748If the obfuscation configuration file specified by consumerFiles contains the following obfuscation rules, these rules will be merged into the obfuscation.txt file in the HAR package.
749
750```
751Obfuscate Options
752-enable-property-obfuscation
753-enable-string-property-obfuscation
754-enable-toplevel-obfuscation
755-compact
756-remove-log
757
758Keep Options
759-keep-property-name
760-keep-global-name
761```
762
763Precautions for Obfuscation in the Library
764
7651. If the obfuscation configuration file specified by consumerFiles contains the preceding obfuscation options, these obfuscation options will be combined with the obfuscation rules of the main module when other modules depend on the HAR package. As a result, the main module is affected. Therefore, you are not advised to configure obfuscation options in the consumer-rules.txt file. You are advised to configure only reserved options.
766
7672. If the -keep-dts option is added to the obfuscation configuration file specified by consumerFiles, it will be converted into -keep-global-name and -keep-property-name.
768
769## Retracing Stack Traces
770
771The function names of an application project after obfuscation are changed. As a result, the stack trace printed during crash is more difficult to understand because it is not completely consistent with the source code. You can use the hstack plugin in DevEco Studio Command Line Tools to restore the source stack trace and analyze problems. The **sourceMap.json** file generated during compilation and the obfuscation name mapping file **nameCache.json** are essential for de-obfuscation. Ensure to back them up locally.
772
773![obfuscation-product](figures/obfuscation-product.png)
774
775## Usage Description
776
777* Currently, custom obfuscation plugins cannot be inserted into the hvigor build process.
778* If a module that depends on an obfuscated HAR enables obfuscation, the HAR will be obfuscated again.
779* To enable the release build mode, select **Product** in the upper right corner of DevEco Studio and set **Build Mode** to **release**.
780![product-release](figures/product-release.png)
781
782## Appendix
783
784### Mappings Between Obfuscate Options and Minimum SDK Versions
785
786| Obfuscate Option| Description | Minimum SDK Version|
787| ------- | --------- | ------ |
788| -disable-obfuscation         | Disables obfuscation.| 4.0.9.2 |
789| -enable-property-obfuscation | Enables property obfuscation.| 4.0.9.2 |
790| -enable-string-property-obfuscation | Enables obfuscation for string literal property names.| 4.0.9.2 |
791| -enable-toplevel-obfuscation | Enables top-level scope name obfuscation.| 4.0.9.2 |
792| -enable-filename-obfuscation | Enables file or folder name obfuscation for the HAR.<br> Enables file or folder name obfuscation for the HAP/HSP.| 4.1.5.3 <br> 5.0.0.19 |
793| -enable-export-obfuscation   | Enables obfuscation for imported or exported names.| 4.1.5.3 |
794| -compact                     | Removes unnecessary spaces and all line feeds.| 4.0.9.2 |
795| -remove-log                  | Removes the expressions involving direct calls to the **console.** statement in specific scenarios.| 4.0.9.2 |
796| -print-namecache             | Saves the name cache to the specified file path.| 4.0.9.2 |
797| -apply-namecache             | Reuses the specified name cache file.| 4.0.9.2 |
798| -remove-comments             | Removes all comments in the file.| 4.1.5.3 |
799| -keep-property-name          | Keeps property names from being obfuscated.| 4.0.9.2 |
800| -keep-global-name            | Keeps top-level scope names from being obfuscated.| 4.0.9.2 |
801| -keep-file-name              | Keeps file or folder names in the HAR from being obfuscated.<br> Keeps file or folder names in the HAP/HSP from being obfuscated.| 4.1.5.3 <br> 5.0.0.19 |
802| -keep-dts                    | Keeps the names in the .d.ts file in the specified path from being obfuscated.| 4.0.9.2 |
803| -keep-comments               | Keeps the classes, functions, namespaces, enums, structs, interfaces, modules, types, and JsDoc comments above properties in the declaration file generated after compilation from being obfuscated.| 4.1.5.3 |
804| -keep                        | Keeps all names in the specified path from being obfuscated.| 5.0.0.18 |
805| Wildcard                      | The keep options of the name classes and path classes support wildcards.| 5.0.0.24 |
806
807### Viewing the Obfuscation Effect
808
809You can find the obfuscated files, name mapping file, and system API trustlist file in the **build** directory of the build product.
810
811* Obfuscated file directory: build/default/[...]/release/moduleName
812* Directory of the name mapping file and system API trustlist file: build/default/[...]/release/obfuscation
813  * The name mapping file, named **nameCache.json**, records the mappings between source code names and names after obfuscation.
814  * The system API trustlist file, named **systemApiCache.json**, records the APIs and property names that will be kept.
815
816  ![build-product](figures/build-product.png)
817
818### Troubleshooting
819
8201. Configure the **-disable-obfuscation** option in **obfuscation-rules.txt** to disable obfuscation, and check whether the exception is caused by obfuscation.
8212. If the function is abnormal after obfuscation is enabled, read the document to understand the capabilities of obfuscation rules, such as [-enable-property-obfuscation](#keep-options), [-enable-toplevel-obfuscation](#keep-options), [-enable-filename-obfuscation](#keep-options), and [-enable-export-obfuscation](#keep-options), and the syntax scenarios that require the configuration of a [trustlist](#keep-options) to ensure that the application functions properly. The following briefly describes the four keep options that are enabled by default. For details, see the complete description of the corresponding options.
822    [-enable-toplevel-obfuscation](#keep-options): keeps top-level scope name from being obfuscated.
823    [-enable-property-obfuscation](#keep-options): keeps properties from being obfuscated. You need to use [-keep-property-name](#keep-options) to configure a trustlist for specified property names in scenarios where obfuscation is not allowed, such as network data access, JSON field access, dynamic property access, and .so library API calls.
824    [-enable-export-obfuscation](#keep-options): keeps exported names from being obfuscated. Generally, this option is used together with the preceding two options. You need to use [-keep-global-name](#keep-options) to configure a trustlist for exported or imported names in scenarios where external APIs of the module cannot be obfuscated.
825    [-enable-filename-obfuscation]: keeps file names from being obfuscated. You need to use [-keep-file-name](#keep-options) to configure a trustlist for file paths and names in scenarios where file paths are dynamically imported or directly loaded at runtime.
8263. If you find a [troubleshooting](#troubleshooting) case similar to your scenario, you can quickly resolve the issue by following the recommended solution.
8274. If no similar case is found, you should identify the issue by examining the configuration functions. If the relevant functions are unnecessary, you can remove the corresponding configuration items.
8285. Analyze application crashes during running as follows:
829    Open the application run log or click the Crash dialog box in DevEco Studio to find the crash stack.
830    The line number in the crash stack is the line number of the [build product](#viewing-the-obfuscation-effect), and the method name may also be the obfuscated name. Therefore, you are advised to check the build product based on the crash stack, analyze the names that cannot be obfuscated, and add them to the trustlist.
8316. If the app does not crash during running but functions are abnormal (for example, a white screen is displayed):
832    1. Open the app run log: Select HiLog, search for logs directly related to the function exception, and locate the context where the problem occurs.
833    2. Locate the abnormal code segment: Analyze logs to find the specific code block that causes the function exception.
834    3. Enhanced log output: Logs are added to the processed data fields in the function code that may be abnormal.
835    4. Analyze and determine key fields: Analyze the output of new logs to check whether the data of this field is abnormal due to confusion.
836    5. Configure the whitelist to protect key fields: Add the key fields that directly affect application functions after obfuscation to the whitelist.
837
838### **FAQs**
839
840#### Errors That May Occur When -enable-property-obfuscation Is Configured
841
842Case 1: The error message "Cannot read property 'xxx' of undefined" is reported.
843
844```
845// Before obfuscation
846const jsonData = ('./1.json')
847let jsonStr = JSON.parse(jsonData)
848let jsonObj = jsonStr.jsonProperty
849
850// After obfuscation
851const jsonData = ('./1.json')
852let jsonStr = JSON.parse(jsonData)
853let jsonObj = jsonStr.i
854```
855
856After property obfuscation is enabled, **jsonProperty** is obfuscated as a random character **i**. However, the original name is used in the JSON file, causing the error.
857
858**Solution**: Use the **-keep-property-name** option to add the fields used in JSON files to the trustlist.
859
860Case 2: An error message is reported when database-related fields are used and property obfuscation is enabled.
861
862The error message is "table Account has no column named a23 in 'INSET INTO Account(a23)'."
863
864Database fields are used in the code. During obfuscation, the field names in the SQL statements are obfuscated, but the original field names are used in the database, causing the error.
865
866**Solution**: Use the **-keep-property-name** option to add the database fields to the trustlist.
867
868#### Errors That May Occur When -enable-export-obfuscation and -enable-toplevel-obfuscation Are Configured
869
870When the two options are configured, method name confusion in the following scenarios is involved when the main module calls the methods of other modules:
871
872| Main Module| Dependent Module| Confusion of Imported and Exported Names|
873| ------- | ------- | ----------------------------|
874| HAP/HSP | HSP     | The HSP and main module are built independently, and different names are generated after obfuscation. Therefore, a trustlist must be configured for both the HSP and main module.|
875| HAP/HSP | Local HAR| The local HAR is built together with the main module. After obfuscation, the names are the same.|
876| HAP/HSP | Third-party library | The names and properties exported from a third-party library are collected to the trustlist. They are not confused during import and export.|
877
878For the HSP, you must add the methods used by other modules to the trustlist. You must add the same trustlist for the main module. Therefore, you are advised to add the obfuscation file configured with the trustlist (for example, **hsp-white-list.txt**) to the obfuscation configuration item of the module that depends on the obfuscation file, that is, the **files** field shown in the following figure.
879
880![obfuscation-config](figures/obfuscation-config.png)
881
882Case 1: When a class is dynamically imported, the class definition is confused, but the class name is not, causing an error.
883
884```
885// Before obfuscation
886export class Test1 {}
887
888let mytest = (await import('./file')).Test1
889
890// After obfuscation
891export class w1 {}
892
893let mytest = (await import('./file')).Test1
894```
895
896The exported class **Test1** is a top-level domain name. When **Test1** is dynamically used, it is a property. Because the **-enable-property-obfuscation** option is not configured, the class name is confused, but the property name is not.
897
898**Solution**: Use the **-keep-global-name** option to add **Test1** to the trustlist.
899
900Case 2: For a method in a namespace, the method definition is confused, but the statement that uses the method is not, causing an error.
901
902```
903// Before obfuscation
904export namespace ns1 {
905  export class person1 {}
906}
907
908import {ns1} from './file1'
909let person1 = new ns1.person1()
910
911// After obfuscation
912export namespace a3 {
913  export class b2 {}
914}
915
916import {a3} from './file1'
917let person1 = new a3.person1()
918```
919
920**person1** in the namespace is a top-level class name. When it is called by using **ns1.person1**, **person1** is a property and is not obfuscated because property obfuscation is not enabled.
921
922**Solution:**
923
9241. Configure the **-enable-property-obfuscation** option.
9252. Use the **-keep-global-name** option to add the methods exported from the namespace to the trustlist.
926
927Case 3: When declare global is used, a syntax error is reported after obfuscation.
928
929```
930// Before obfuscation
931declare global {
932  var age : string
933}
934
935// After obfuscation
936declare a2 {
937  var b2 : string
938}
939```
940
941The error message "SyntaxError: Unexpected token" is reported.
942
943**Solution**: Use **-keep-global-name** to **add __global** to the trustlist.
944
945#### The **-enable-string-property-obfuscation** option is not configured, but the string literal property name is obfuscated. As a result, the value of the string literal property name is undefined.
946
947```
948person["age"] = 22; // Before obfuscation
949
950person["b"] = 22; // After obfuscation
951```
952
953**Solution:**
954
9551. Check whether **-enable-string-property-obfuscation** is configured for the dependent HAR. If it is configured, the main project will be affected, and you should disable it.
9562. If it must be configured, add the property name to the trustlist.
9573. If it is not configured and the SDK version is earlier than 4.1.5.3, update the SDK.
958
959#### Errors That May Occur When -enable-filename-obfuscation Is Configured
960
961Case 1: The error message "Error Failed to get a resolved OhmUrl for 'D:code/MyApplication/f12/library1/pages/d.ets' imported by 'undefined'" is reported.
962
963As shown below, the outer layer of the **library1** module contains a directory named **directory**. When file name obfuscation is enabled, **directory** is obfuscated as **f12**, causing the error indicating that the path is not found.
964
965![directory-offuscation](figures/directory-obfuscation.png)
966
967**Solution:**
968
9691. If the project directory structure and error message are similar, update the SDK to 5.0.0.26 or later.
9702. Use the **-keep-file-name** option to add the directory name **directory** of the module to the trustlist.
971
972Case 2: The error message "Cannot find module 'ets/appability/AppAbility' which is application Entry Point" is reported.
973
974The system loads the ability file when the application is running. Therefore, you must manually configure the trustlist to prevent the specified file from being obfuscated.
975
976**Solution**: Use the **-keep-file-name** option to add the path corresponding to the **srcEntry** field in the **src/main/module.json5** file to the trustlist.
977
978```
979-keep-file-name
980appability
981AppAbility
982```
983
984#### Errors That May Occur When -keep-global-name and a Trustlist Are Configured
985
986The error message "Cannot read properties of undefined (reading 'has')" is reported.
987
988**Solution**: Upgrade the SDK to 4.1.6.3 or later.
989
990#### The HAP and HSP depend on the same local source code HAR module.
991
992* If file name obfuscation is enabled, the following problems may occur:
993  * Problem 1: The singleton function is abnormal. The reason is that the build and obfuscation processes of HAP and HSP are executed independently. In the local source code HAR module, the same file name may be obfuscated into different file names in the HAP and HSP packages.
994  * Problem 2: The interface fails to be called. The reason is that the build and obfuscation processes of HAP and HSP are executed independently. In the local source code HAR module, different file names may be obfuscated into the same file name in the HAP and HSP packages.
995* If the -enable-export-obfuscation and -enable-toplevel-obfuscation options are enabled, the interface fails to be loaded during application running.
996The reason is that HAP and HSP independently execute the build and obfuscation processes. The interfaces exposed in the HAR module of the local source code are obfuscated into different names in HAP and HSP.
997
998**Solution:**
9991. Change the local source code HAR on which HAP and HSP depend to [bytecode HAR](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/ide-hvigor-build-har-V5#section179161312181613). In this way, the HAR will not be confused when it is depended on.
10002. The local source code HAR on which HAP and HSP depend is [built and packaged in release mode](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/ide-hvigor-build-har-V5#section19788284410). In this way, when the HAR is depended on, its file name is not confused with the external interface.
1001