• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Obfuscation Principles and Capabilities of ArkGuard
2
3## Glossary
4
5| Term| Definition|
6| --- | --- |
7| [HAP](../quick-start/hap-package.md) | The Harmony Ability Package (HAP) is the basic unit for installing and running applications. It is a module package generated by packaging code, resources, third-party libraries, and configuration files.|
8| [HAR](../quick-start/har-package.md) | A Harmony Archive (HAR) is a static shared package that enables multiple modules or projects to share code such as ArkUI components and resources. It is created by using a static library.|
9| [HSP](../quick-start/in-app-hsp.md) | A Harmony Shared Package (HSP) is a dynamic shared package for sharing code and resources. It is created by using a shared library.|
10| Local HAR| HAR module in source code form.|
11| Remote HAR| HAR generated after the build.|
12| Local HSP| HSP module in source code form.|
13| Remote HSP| HSP generated after the build.|
14| Third-party library| Libraries developed by third parties and published to the OpenHarmony Third-Party Library Repository.|
15| Name obfuscation| Changing class names, method names, variable names, and other identifiers to meaningless names.|
16
17## Scope of Obfuscation Capabilities
18
19### Supported Languages
20ArkGuard supports ArkTS, TS, and JS, but not C/C++, JSON, or resource files.
21
22### Obfuscation Capabilities
23ArkGuard provides basic name obfuscation, code compression, and comment removal, but does not support advanced features like control obfuscation or data obfuscation.
24
25It primarily offers name renaming and trustlist configuration for retention.
26
27### Limitations of Obfuscation Capabilities
28
29**Language Limitations**
30
31Code obfuscation tools vary in type analysis mechanisms, obfuscation strategies, and execution efficiency based on the target language. For example, ProGuard targets strongly-typed languages like Java, where each type has a clear definition source. This feature makes the type relationship tracing and processing in the obfuscation process more accurate, greatly reducing the need for retention rules.
32
33In contrast, ArkGuard targets JS, TS, and ArkTS. JS supports dynamic modification of objects and functions at runtime, but obfuscation is a static process in the compilation phase. This difference may cause a failure in parsing obfuscated named at runtime, resulting in runtime exceptions. TS and ArkTS use a structural type system, where different named types with the same structure are considered as equivalent types. Therefore, it is difficult to trace the exact source of types. As such, when using ArkGuard, you need to configure trustlists for more syntax scenarios. Moreover, ArkGuard uses a global property retention mechanism that retains all properties with the same name according to the trustlist. It does not support precise retention settings for specific types.
34
35To illustrate, consider this example:
36
37Assume that ArkGuard allows the configuration of a trustlist for specific types. If class A1 is configured in a trustlist with its property prop1, but prop1 in class A2 is not in the trustlist, passing an instance of A2 (a2) to the **test** function would cause issues when accessing the prop1 property.
38
39```typescript
40// Before obfuscation:
41class A1 {
42  prop1: string = '';
43}
44
45class A2 {
46  prop1: string = '';
47}
48
49function test(input: A1) {
50  console.log(input.prop1);
51}
52
53let a2 = new A2();
54a2.prop1 = 'prop a2';
55test(a2);
56```
57
58```typescript
59// After obfuscation:
60class A1 {
61  prop1: string = '';
62}
63
64class A2 {
65  a: string = '';
66}
67
68function test(input: A1) {
69  console.log(input.prop1);
70}
71
72let a2 = new A2();
73a2.a = 'prop a2';
74test(a2);
75```
76
77You should be aware of these differences and use unique names to achieve better obfuscation results.
78
79**Limited security assurance**
80
81Like other obfuscation tools, ArkGuard increases reverse engineering difficulty but cannot prevent it entirely.
82
83You should not rely solely on ArkGuard for security. For higher security requirements, consider [application encryption](https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V5/code-protect-V5) and third-party hardening measures.
84
85## Obfuscation Mechanism and Process
86
87The following figure shows a simplified compilation process.
88
89![compilation-process](figures/compilation-process.png)
90
91You can enable the obfuscation feature in the **build-profile.json5** file of the module so that the source code can be automatically obfuscated during compilation and packaging.
92
93During obfuscation, the tool reads the obfuscation switch. If the switch is enabled, it parses the obfuscation configuration file, merges rules according to the [merging strategies](#obfuscation-rule merging-strategies), applies obfuscation to intermediate files (generated after syntax conversion), and writes the obfuscated files to the **build** directory. You can verify the obfuscation effect by examining the output in the **build** directory.
94
95Before using obfuscation, you are advised to learn about the capabilities of [obfuscation options](source-obfuscation.md#obfuscation-options) and [retention options](source-obfuscation.md#retention-options), and select the appropriate capabilities for your needs.
96
97
98## Obfuscation Options
99
100### Summary of Existing Obfuscation Options
101
102| Function| Option|
103| --- | --- |
104| Disabling obfuscation| [`-disable-obfuscation`](#-disable-obfuscation) |
105| Obfuscating property names| [`-enable-property-obfuscation`](#-enable-property-obfuscation) |
106| Obfuscating string literal property names| [`-enable-string-property-obfuscation`](#-enable-string-property-obfuscation) |
107| Obfuscating top-level scope names| [`-enable-toplevel-obfuscation`](#-enable-toplevel-obfuscation) |
108| Obfuscating imported/exported names| [`-enable-export-obfuscation`](#-enable-export-obfuscation) |
109| Obfuscating file names| [`-enable-filename-obfuscation`](#-enable-filename-obfuscation) |
110| Compressing code| [`-compact`](#-compact) |
111| Removing declaration file comments| [`-remove-comments`](#-remove-comments) |
112| Removing console logs| [`-remove-log`](#-remove-log) |
113| Printing name caches| [`-print-namecache`](#-print-namecache) |
114| Reusing name caches| [`-apply-namecache`](#-apply-namecache) |
115| Printing unobfuscated names| [`-print-kept-names`](#-print-kept-names) |
116| Reducing the default language trustlist| [`-extra-options strip-language-default`](#-extra-options-strip-language-default) |
117| Reducing the default system API trustlist| [`-extra-options strip-system-api-args`](#-extra-options-strip-system-api-args) |
118| Retaining declaration file parameters| [`-keep-parameter-names`](#-keep-parameter-names) |
119| Merging dependent module options| [`-enable-lib-obfuscation-options`](#-enable-lib-obfuscation-options) |
120| Marking trustlists in source code by comments| [`-use-keep-in-source`](#-use-keep-in-source) |
121
122### -disable-obfuscation
123
124Disables code obfuscation.
125
126If this option is configured, the default obfuscation capabilities (local variables and parameter names) and all configured obfuscation and retention options become invalid.
127
128### -enable-property-obfuscation
129
130Enables property name obfuscation. The effect is as follows:
131
132  ```
133  // Before obfuscation:
134  class TestA {
135    static prop1: number = 0;
136  }
137  TestA.prop1;
138  ```
139
140  ```
141  // After obfuscation:
142  class TestA {
143    static i: number = 0;
144  }
145  TestA.i;
146  ```
147
148If this option is configured, all property names except the following are obfuscated:
149
150* Property names of classes and objects that are directly imported or exported by using **import** or **export**. For example, the property name **data** in the following example is not obfuscated.
151
152    ```
153    export class MyClass {
154       data: string;
155    }
156    ```
157
158* Property names in ArkUI components. For example, **message** and **data** in the following example are not obfuscated.
159
160    ```
161    @Component struct MyExample {
162        @State message: string = "hello";
163        data: number[] = [];
164        // ...
165    }
166    ```
167
168* Property names specified in [retention options](#-keep-property-name).
169* Property names in the SDK API list. The SDK API list is a set of names automatically extracted from the SDK during build. Its cache file is **systemApiCache.json**, which is stored in **build/default/cache/{...}/release/obfuscation** in the project directory.
170* String literal property names. For example, **"name"** and **"age"** in the following example are not obfuscated.
171
172    ```
173    let person = {"name": "abc"};
174    person["age"] = 22;
175    ```
176
177### -enable-string-property-obfuscation
178
179Enables obfuscation of string literal property names. It is effective only if property name obfuscation is enabled.
180
181To obfuscate string literal property names, you must use this option together with **-enable-property-obfuscation**. Example:
182
183  ```
184  -enable-property-obfuscation
185  -enable-string-property-obfuscation
186  ```
187
188According to the preceding configuration, the obfuscation effect of **"name"** and **"age"** is as follows:
189
190  ```
191  // Before obfuscation:
192  let person = {"name": "abc"};
193  person["age"] = 22;
194  ```
195
196  ```
197  // After obfuscation:
198  let person = {"a": "abc"};
199  person["b"] = 22;
200  ```
201
202
203
204**NOTE**
205
206**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 retained using [retention options](#-keep-property-name). Special characters refer to characters other than lowercase letters a-z, uppercase letters A-Z, digits 0-9, and underscores (_).
207
208**2.** The property trustlist of the SDK API list does not contain 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.
209```
210// Part of the SDK API file @ohos.app.ability.wantConstant:
211export enum Params {
212  ACTION_HOME = 'ohos.want.action.home'
213}
214// Source code example:
215let params = obj['ohos.want.action.home'];
216```
217
218When the **-enable-string-property-obfuscation** option is used, use the [-keep-property-name](#-keep-property-name) option if you want to retain the property names in the SDK API string constants in the source code, for example, **obj['ohos.want.action.home']**.
219
220### -enable-toplevel-obfuscation
221
222Enables obfuscation of top-level scope names. The effect is as follows:
223
224  ```
225  // Before obfuscation:
226  let count = 0;
227  ```
228
229  ```
230  // After obfuscation:
231  let s = 0;
232  ```
233
234If this option is configured, the names of all top-level scopes except the following are obfuscated:
235
236* Names that are directly imported or exported by using **import** or **export**.
237* Top-level scope names that are not declared in the current file.
238* Top-level scope names specified by [retention options](#-keep-global-name).
239* Top-level scope names in the SDK API list.
240
241### -enable-export-obfuscation
242
243Enables obfuscation for imported/exported names. The effect is as follows:
244
245  ```
246  // Before obfuscation:
247  namespace ns {
248    export type customT = string;
249  }
250  ```
251
252  ```
253  // After obfuscation:
254  namespace ns {
255    export type h = string;
256  }
257  ```
258
259If this option is configured, names imported/exported in non-top-level scopes will be obfuscated. To obfuscate names imported/exported in the top-level scope, use this option with **-enable-toplevel-obfuscation**. To obfuscate imported or exported property names, use this option **-enable-property-obfuscation**. Note the following special scenarios:
260
261* Names exported from remote HARs (packages whose real paths are in **oh_modules**) and their property names are not obfuscated.
262* Names and property names specified by [retention options](#retention-options) are not obfuscated.
263* Names in the SDK API list are not obfuscated.
264
265### -enable-filename-obfuscation
266
267Enables obfuscation of file/folder names. The effect is as follows:
268
269  ```
270  // Before obfuscation:
271  import * as m from '../test1/test2';
272  import { foo } from '../test1/test2';
273  const module = import('../test1/test2');
274  ```
275
276
277  ```
278  // After obfuscation:
279  import * as m from '../a/b';
280  import { foo } from '../a/b';
281  const module = import('../a/b');
282  ```
283
284If this option is configured, all file/folder names except the following are obfuscated:
285
286* File or folder names specified by the **main** and **types** fields in the **oh-package.json5** file.
287* File or folder names specified by the **srcEntry** field in the **module.json5** file of the module.
288* File or folder names specified by [-keep-file-name](#-keep-file-name).
289* File or folder names in non-ECMAScript module reference mode (for example, const module = require('./module')).
290* File or folder names in non-path reference mode. For example, **json5** in the example **import module from 'json5'** is not obfuscated.
291
292>**NOTE**
293>
294>For files that the system needs to load files during application running, manually configure them into a trustlist using the [-keep-file-name](#-keep-file-name) option. Otherwise, the application may fail to run.
295>
296>The 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.
297
298### -compact
299
300Removes unnecessary spaces and all line feeds.
301
302If this option is configured, all code is compressed to one line. The effect is as follows:
303
304  ```
305  // Before obfuscation:
306  class TestA {
307    static prop1: number = 0;
308  }
309  TestA.prop1;
310  ```
311
312  ```
313  // After obfuscation:
314  class TestA { static prop1: number = 0; } TestA.prop1;
315  ```
316
317>**NOTE**
318>
319>The 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.
320
321
322### -remove-comments
323
324Removes JsDoc comments from the declaration file generated after compilation. The effect is as follows:
325
326Before obfuscation:
327  ```
328  /**
329   * @todo
330   */
331  declare let count: number;
332  ```
333
334After obfuscation:
335  ```
336  declare let count: number;
337  ```
338
339You can configure [-keep-comments](#-keep-comments) to retain the JsDoc comments in the declaration file.
340
341>**NOTE**
342>
343>By default, all comments in the source code file generated after the compilation are removed and cannot be retained.
344
345### -remove-log
346
347Removes calls to console.* statements, provided the return value is not used. The effect is as follows:
348
349  ```
350  // Before obfuscation:
351  if (flag) {
352    console.log("hello");
353  }
354  ```
355
356  ```
357  // After obfuscation:
358  if (flag) {
359  }
360  ```
361
362If this option is configured, the console.* statements in the following scenarios are removed:
363
3641. Calls at the top layer of a file.
3652. Calls within a code block.
366   Example:
367   ```
368   function foo() {
369    console.log('in block');
370   }
371   ```
3723. Calls with a module or namespace.
373   Example:
374   ```
375   namespace ns {
376    console.log('in ns');
377   }
378   ```
3794. Calls within a **switch** statement.
380
381### -print-namecache
382
383Saves the name cache to the specified file path. The name cache contains the mappings of names before and after obfuscation. The **filepath** parameter is mandatory. It supports relative and absolute paths. For a relative path, the start point is the current directory of the obfuscation configuration file. The file name extension in **filepath** must be .json.
384
385Example:
386```
387-print-namecache
388./customCache/nameCache.json
389```
390
391>**NOTE**
392>
393>A new **namecache.json** file is generated each time the module if fully built. Therefore, save a copy of the file each time you publish a new version.
394
395### -apply-namecache
396
397Reuses a name cache file in the specified file path. The **filepath** parameter is mandatory. It supports relative and absolute paths. For a relative path, the start point is the current directory of the obfuscation configuration file. The file name extension in **filepath** must be .json.
398This option should be used in incremental build scenarios. After this option is enabled, the names will be obfuscated according to the cache mappings. If there is no corresponding name, new random names are used.
399
400Example:
401```
402-apply-namecache
403./customCache/nameCache.json
404```
405
406By default, DevEco Studio saves cache files in a temporary cache directory and automatically applies the cache files during incremental build.
407Default cache directory: **build/default/cache/{...}/release/obfuscation**
408
409### -print-kept-names
410
411Prints the unobfuscated list and full trustlist to the specified file path. The **filepath** parameter is optional. It supports relative paths, with the start point being the current directory of the obfuscation configuration file. The file name extension in **filepath** must be .json.
412
413If the **filepath** parameter is not specified, the unobfuscated list (**keptNames.json**) and full trustlist (**whitelist.json**) are output to the cache directory **build/default/cache/{...}/release/obfuscation** by default.
414
415If the **filepath** parameter is specified, the unobfuscated list is also exported to the path specified by this parameter.
416
417The full trustlist collected during a full build is classified into the following types:
418
419(1) 'sdk': system APIs.
420
421(2) 'lang': keywords in the language.
422
423(3) 'conf': trustlist in the user-defined retention options.
424
425(4) 'struct': properties in ArkUI structs.
426
427(5) 'exported': names and properties exported.
428
429(6) 'strProp': string properties.
430
431(7) 'enum': enum members.
432
433The 'sdk' trustlist is exported to the **systemApiCache.json** file in the **build/default/cache/{...}/release/obfuscation/** directory, and other trustlists are exported to the **whitelist.json** file.
434
435The **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 literal property name obfuscation is disabled), or enum trustlist.
436
437**NOTE**
438
439**1.** During HAR module compilation with property name obfuscation enabled, enum member names are collected into the 'enum' trustlist.
440Example:
441```
442enum Test {
443  member1,
444  member2
445}
446```
447The 'enum' trustlist includes names such as ['member1', 'member2']. This requirement stems from the fact that, in earlier HAR module versions, the compilation process produced JS files. In these JS files, enums are represented as immediately invoked functions, with enum members expressed as string properties and constants. To maintain proper functionality during property name obfuscation, these enum member names must be added to the trustlist. This practice continues to be applied when compiling the latest bytecode HAR modules.
448
449**2.** During HAP/HSP/bytecode HAR module compilation with property name obfuscation enabled, variable names in initialization expressions of enum members are collected into the 'enum' trustlist.
450Example:
451```
452let outdoor = 1;
453enum Test {
454  member1,
455  member2 = outdoor + member1 + 2
456}
457```
458In the case of HAP/HSP module compilation, the content of the 'enum' trustlist is ['outdoor', 'member1']. In the case of bytecode HAR module compilation, the content is ['outdoor', 'member1', 'member2'].
459
460### -extra-options strip-language-default
461
462By default, the default language trustlist contains the names of APIs related to DOM, WebWorker, and ScriptHost in the TS system interfaces, as well as the names of Web APIs. If property names in the source code match these names, they will be retained.
463
464To obfuscate these parts of the code, configure the **-extra-options strip-language-default** option.
465
466You can determine the specific reduction range of APIs retained by default as follows:
467
468Enable the **-print-kept-names** option and compare the differences in the **lang** field of the **whitelist.json** file when the **-extra-options strip-language-default** option is enabled and disabled. The difference represents the specific reduction range of the default language trustlist.
469
470### -extra-options strip-system-api-args
471
472By default, the system API trustlist contains local variable names in system APIs and is effective for local variables in your source code by default. If property names in the source code match local variables in system APIs or if local variables in the source code match the system API trustlist, these property names and local variables will be retained.
473
474To obfuscate these parts of the code, configure the **-extra-options strip-system-api-args** option.
475
476The specific content of the system API trustlist can be viewed in the **systemApiCache.json** file through the **ReservedLocalNames**, **ReservedPropertyNames**, and **ReservedGlobalNames** fields. This file, located in the directory **build/default/cache/{...}/release/obfuscation**, records the interface and property names in the SDK, and source code with matching names will not be obfuscated.
477
478You can determine the specific reduction range of the system API trustlist as follows:
479
480Compare the differences in the **ReservedLocalNames** and **ReservedPropertyNames** fields of the **systemApiCache.json** file when the **-extra-options strip-system-api-args** option is enabled and disabled. The difference represents the specific reduction range of the system API trustlist. However, the content of the **ReservedGlobalNames** field will not change.
481
482**How to use -extra-options**
483
484To enable trustlist optimization, add the **-extra-options** prefix directly before the option in the obfuscation configuration file, with no additional content in between. You can enable either one option or both options, like shown in the following examples:
485
486One option enabled:
487
488```
489-extra-options
490strip-language-default
491
492-extra-options strip-language-default
493```
494
495Both options enabled:
496
497```
498-extra-options strip-language-default, strip-system-api-args
499
500-extra-options strip-language-default strip-system-api-args
501
502-extra-options strip-language-default
503-extra-options strip-system-api-args
504```
505
506### -keep-parameter-names
507Retains parameter names in declaration files for exported interfaces. The effect is as follows:
508- For functions and class member methods, if the function or method name is not confused, their parameter names are retained.
509- For class constructors, if the class name is not obfuscated, their parameter names in the constructors are retained.
510
511**NOTE**
512
513**1.** Parameter names that are not in the preceding scenarios (such as anonymous functions) will still be obfuscated.
514
515**2.** Parameter names in source code files will be obfuscated regardless of this option.
516
517### -enable-lib-obfuscation-options
518Merges obfuscation options of dependent modules into the obfuscation configuration of the current module.
519
520Obfuscation configuration includes [obfuscation options](#obfuscation-options) and [retention options](#retention-options).
521- By default, the effective obfuscation configuration is the merged result of the current module's obfuscation configuration and the dependent modules' retention options.
522- When this option is configured, the effective obfuscation configuration is the merged result of the current module's obfuscation configuration and the dependent modules' obfuscation configuration.
523
524For details about the merging logic, see [Obfuscation Rule Merging Strategies](#obfuscation-rule-merging-strategies).
525
526### -use-keep-in-source
527
528Marks trustlists in .ts or .ets source code using the following two comment annotations (declaration files are not supported):
529
530// @KeepSymbol: This annotation is used to mark names that should be retained. It is usually placed on the line above the relevant code to ensure that the name is not obfuscated when the code is compiled.
531
532// @KeepAsConsumer: This annotation is used to mark names that should be retained. It is usually placed on the line above the relevant code to ensure that the name is not obfuscated when the code is compiled. In HAR/HSP modules, names marked with @KeepAsConsumer are also listed in the **obfuscation.txt** file. In HAP modules, @KeepAsConsumer works exactly like @KeepSymbol.
533
534
535
536The examples below use // @KeepSymbol, but // @KeepAsConsumer can be used in the same way for the same purposes.
537
538#### Classes
539
540You can mark the following elements in a class:
541
542- Class declarations
543- Constructors
544- Fields and methods
545
546**Example**
547
548```typescript
549// Retain the class name and all member names.
550// @KeepSymbol
551class MyClass01 {
552  prop01: string = "prop"; // MyClass01 and prop01 are not obfuscated.
553}
554
555// Use the constructor to retain the class name.
556class MyClass02 {
557  prop02: string = "prop";
558  // @KeepSymbol
559  constructor() {}; // MyClass02 is not obfuscated.
560}
561
562// Retain the class name and specified field and method names. MyClass03, prop03_1, and method03_2 in the class are not obfuscated.
563class MyClass03 {
564  // @KeepSymbol
565  prop03_1: string = "prop";
566  prop03_2: number = 1;
567  constructor() {};
568
569  method03_1(): void {};
570  // @KeepSymbol
571  method03_2(): void {};
572}
573```
574
575#### Interfaces
576
577You can mark the following elements in an interface:
578
579- Interface declarations
580- Fields and methods
581
582**Example**
583
584```typescript
585// Retain the interface name and all member names. MyInterface01, name01, and foo01 are not obfuscated.
586// @KeepSymbol
587interface MyInterface01 {
588  name01: string;
589  foo01(): void;
590}
591
592// Retain the interface name and specified field and method names. MyInterface02 and name02 are not obfuscated.
593interface MyInterface02 {
594  // @KeepSymbol
595  name02: string;
596  foo02(): void;
597}
598```
599
600#### Enums
601
602You can mark the following elements in an enum:
603
604- Enum declarations
605- Enum members
606
607**Example**
608
609```typescript
610// Retain the enum name and all member names. Color01, RED01, and BLUE01 are not obfuscated.
611// @KeepSymbol
612enum Color01 {
613  RED01,
614  BLUE01
615}
616
617// Retain the specified enum member name.
618enum Color02 {
619  RED02,
620  // @KeepSymbol
621  BLUE02 // Color02 and BLUE02 are not obfuscated.
622}
623```
624
625#### Functions
626
627Currently, function names can be marked.
628
629**Example**
630
631```typescript
632// Retain the function name. MyAdd is not obfuscated.
633// @KeepSymbol
634function MyAdd(a: number, b:number): number {
635  return a + b;
636}
637```
638
639#### Namespaces
640
641Currently, namespace names can be marked.
642
643**Example**
644
645```typescript
646// Retain the namespace name and the member names directly exported internally. MyNameSpace and foo are not obfuscated.
647// @KeepSymbol
648namespace MyNameSpace {
649  export function foo(){};
650  function bar(){};
651}
652```
653
654#### Global Variables
655
656Currently, only global variables can be marked. Local variables cannot be marked.
657
658**Example**
659
660```typescript
661// Retain the marked variable name. myVal is not obfuscated.
662// @KeepSymbol
663const myVal = 1;
664```
665
666#### Trustlist Addition Rules
667
668Marked names are added to the obfuscation trustlist based on the following rules. Names kept by **KeepAsConsumer** are also recorded in the **obfuscation.txt** file.
669
670* If a name is at the top level or directly exported, it goes into -keep-global-name.
671
672* If a name is directly exported, it also goes into -keep-property-name.
673
674* If a name is a property, it goes into -keep-property-name.
675
676* Local variable names are not added to the trustlist (they are not kept).
677
678**Example**
679
680```typescript
681// @KeepAsConsumer
682export class MyClass {
683  prop01: string = "prop";
684}
685```
686In this example, MyClass is added to -keep-global-name and -keep-property-name, and prop01 is added to -keep-property-name. They are also written into the **obfuscation.txt** file.
687
688#### -Scenarios Not Supported by -use-keep-in-source
689
690String properties, numeric properties, and computed properties are not supported.
691
692**Example**
693
694```typescript
695const myMethodName = "myMethod";
696
697// 11, aa, and myMethod are not added to the trustlist.
698class MyClass01 {
699  // @KeepSymbol
700  11:11;
701  // @KeepSymbol
702  'aa':'aa';
703  // @KeepSymbol
704  [myMethodName](){}
705}
706
707// RED is not added to the trustlist.
708enum MyEnum {
709  // @KeepSymbol
710  'RED',
711  BLUE
712}
713```
714
715## Retention Options
716
717### Summary of Existing Retention Options
718
719| Function| Option|
720| --- | --- |
721| Retaining specified property names| [`-keep-property-name`](#-keep-property-name) |
722| Retaining specified top-level scope names or imported/exported element names| [`-keep-global-name`](#-keep-global-name) |
723| Retaining specified file/folder names| [`-keep-file-name`](#-keep-file-name) |
724| Retaining specified comments| [`-keep-comments`](#-keep-comments) |
725| Retaining all names in specified declaration files| [`-keep-dts`](#-keep-dts) |
726| Retaining all names in specified source code files| [`-keep`](#-keep) |
727
728### -keep-property-name
729
730Retains the specified property names. [Name wildcards](#name-wildcards) are supported. The following configuration is used to retain properties named **age**, **firstName**, and **lastName**:
731
732```
733-keep-property-name
734age
735firstName
736lastName
737```
738
739**NOTE**
740
741**1.** This option takes effect when **-enable-property-obfuscation** is used.
742
743**2.** The property trustlist applies globally. That is, if multiple properties with the same name exist in the code, they will not be confused as long as they match the names in the trustlist configured in **-keep-property-name**.
744
745**Which property names should be retained?**
746
7471. To ensure correct obfuscation, you are advised to retain all properties that are not accessed using dot notation. For example, object properties accessed via strings:
748
749   ```
750   var obj = {x0: 0, x1: 0, x2: 0};
751   for (var i = 0; i <= 2; i++) {
752       console.info(obj['x' + i]);  // x0, x1, and x2 should be retained.
753   }
754
755   Object.defineProperty(obj, 'y', {});  // y should be retained.
756   Object.getOwnPropertyDescriptor(obj, 'y');  // y should be retained.
757   console.info(obj.y);
758
759   obj.s = 0;
760   let key = 's';
761   console.info(obj[key]);        // The variable value s corresponding to key should be retained.
762
763   obj.t1 = 0;
764   console.info(obj['t' + '1']);        // t1 should be retained.
765   ```
766
767   For the following string literal property calls, you can choose to retain them.
768
769   ```
770   // Obfuscation configuration:
771   // -enable-property-obfuscation
772   // -enable-string-property-obfuscation
773
774   obj.t = 0;
775   console.info(obj['t']); // 't' will be correctly confused, and t can be retained.
776
777   obj.['v'] = 0;
778   console.info(obj['v']); // 'v' will be correctly confused, and v can be retained.
779   ```
780
7812. In 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 [retention options](#retention-options) to retain 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 [retention options](#retention-options) to retain them.
782
783   ```
784   export class MyClass {
785       person = {name: "123", age: 100};
786   }
787   ```
788
7893. If an API (for example, **foo** in the example) of the .so library needs to be used in the ArkTS/TS/JS file, manually retain the API name.
790
791   ```
792   import testNapi from 'library.so'
793   testNapi.foo() // foo should be retained Example: -keep-property-name foo
794   ```
795
7964. Fields used in JSON parsing and object serialization should be retained.
797
798   ```
799   // Example JSON file structure (test.json):
800   /*
801   {
802     "jsonProperty": "value",
803     "otherProperty": "value2"
804   }
805   */
806
807   const jsonData = fs.readFileSync('./test.json', 'utf8');
808   let jsonObj = JSON.parse(jsonData);
809   let jsonProp = jsonObj.jsonProperty; // jsonProperty should be retained.
810
811   class jsonTest {
812     prop1: string = '';
813     prop2: number = 0
814   }
815
816   let obj = new jsonTest();
817   const jsonStr = JSON.stringify(obj); // prop1 and prop2 will be obfuscated and should be retained.
818   ```
819
8205. Database-related fields should be manually retained. For example, properties in the database key-value pair type (ValuesBucket):
821
822   ```
823   const valueBucket: ValuesBucket = {
824     'ID1': ID1, // ID1 should be retained.
825     'NAME1': name, // NAME1 should be retained.
826     'AGE1': age, // AGE1 should be retained.
827     'SALARY1': salary // SALARY1 should be retained.
828   }
829   ```
830
8316. When custom decorators are used on member variables, member methods, or parameters in the source code, and the intermediate product of source code compilation is a JS file (for example, compiling release-mode source code HAR or source code containing @ts-ignore or @ts-nocheck), the names of these member variables or member methods should be retained. This is because the names of these member variables/methods are hardcoded as string literals during conversion from TS syntax to standard JS syntax.
832
833   Example:
834
835   ```
836   class A {
837     // 1. Member variable decorator
838     @CustomDecoarter
839     propertyName: string = ""   // propertyName should be retained.
840     // 2. Member method decorator
841     @MethodDecoarter
842     methodName1(){} // methodName1 should be retained.
843     // 3. Method parameter decorator
844     methodName2(@ParamDecorator param: string): void { // methodName2 should be retained.
845     }
846   }
847   ```
848
849### -keep-global-name
850
851Retains the specified top-level scope names or imported/exported element names. [Name wildcards](#name-wildcards) are supported. You can perform the configuration as follows:
852
853```
854-keep-global-name
855Person
856printPersonName
857```
858
859Names exported from the namespace can also be retained using the **-keep-global-name** option. The following is an example:
860
861```
862export namespace Ns {
863  export const age = 18; // -keep-global-name age: retains variable age.
864  export function myFunc () {}; // -keep-global-name myFunc: retains function myFunc.
865}
866```
867
868> **NOTE**
869>
870> The trustlist specified by `-keep-global-name` applies globally. That is, if multiple top-level scope names or exported names exist in the code, they will not be confused as long as they match the names in the trustlist configured in **-keep-global-name**.
871
872**Which top-level scope names should be retained?**
873
8741. In JS, 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 retained.
875
876   Example:
877
878   ```
879   var a = 0;
880   console.info(globalThis.a);  // a should be retained.
881
882   function foo(){}
883   globalThis.foo();           // foo should be retained.
884
885   var c = 0;
886   console.info(c);             // c can be correctly obfuscated.
887
888   function bar(){}
889   bar();                      // bar can be correctly obfuscated.
890
891   class MyClass {}
892   let d = new MyClass();      // MyClass can be correctly obfuscated.
893   ```
894
8952. When importing API names from .so libraries using named imports, if both **-enable-toplevel-obfuscation** and **-enable-export-obfuscation** are configured, the API names should be manually retained.
896
897   ```
898   import { testNapi, testNapi1 as myNapi } from 'library.so' // testNapi and testNapi1 should be retained.
899   ```
900
901### -keep-file-name
902
903Retains the file/folder names. You do not need to specify the file name extension. [Name wildcards](#name-wildcards) are supported. Example:
904
905```
906-keep-file-name
907index
908entry
909```
910
911**Which file names should be retained?**
912
9131. When **require** is used to import file paths, the path should be retained. This is because ArkTS does not support [CommonJS](../arkts-utils/module-principle.md#commonjs module) syntax.
914
915   ```
916   const module1 = require('./file1')   // file1 should be retained.
917   ```
918
9192. For dynamically imported paths, since it is impossible to determine whether the parameter in the **import** function is a path, the path should be retained.
920
921   ```
922   const moduleName = './file2'         // The path name file2 corresponding to moduleName should be retained.
923   const module2 = import(moduleName)
924   ```
925
9263. When [dynamic routing](../ui/arkts-navigation-navigation.md#cross-package-dynamic-routing) is used for navigation, the path passed to the dynamic routing should be retained. Dynamic routing provides two modes: system routing table and custom routing table. If a custom routing table is used for redirection, the way to configure a trustlist is consistent with the second dynamic reference scenario. However, if the system routing table is used for redirection, the path corresponding to the **pageSourceFile** field in the **resources/base/profile/route_map.json** file of the module should be added to the trustlist.
927
928   ```
929     {
930       "routerMap": [
931         {
932           "name": "PageOne",
933           "pageSourceFile": "src/main/ets/pages/directory/PageOne.ets",  // The path should be retained.
934           "buildFunction": "PageOneBuilder",
935           "data": {
936             "description" : "this is PageOne"
937           }
938         }
939       ]
940     }
941   ```
942
943### -keep-comments
944
945Retains the classes, functions, namespaces, enums, structs, interfaces, modules, types, and JsDoc comments above properties in the declaration files generated after compilation. [Name wildcards](#name-wildcards) are supported. For example, to retain the JSDoc comments above the **Human** class in the declaration file, use the following configuration:
946
947```
948-keep-comments
949Human
950```
951
952**NOTE**
953
954**1.** This option takes effect when **-remove-comments** is used.
955
956**2.** 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 retained using **-keep-comments**. For example, when **exportClass** is configured in **-keep-comments**, if the class name is **exportClass** obfuscated, its JSDoc comments cannot be retained:
957
958```
959/*
960 * @class exportClass
961 */
962export class exportClass {}
963```
964
965### -keep-dts
966
967Adds names (such as variable names, class names, and property names) in the .d.ts file of the specified file path into the trustlist of **-keep-global-name** and **-keep-property-name**. 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.
968
969### -keep
970
971Retains all names (such as variable names, class names, and property names) in the specified relative file path. **filepath** can be a file or directory. If it is a directory, the files in the directory and subdirectories are not obfuscated.
972
973**filepath** must be a relative path. **./** and **../** are relative to the directory where the obfuscation configuration file is located. [Path wildcards](#path-wildcards) are supported.
974
975```
976-keep
977./src/main/ets/fileName.ts   // Names in the fileName.ts file are not obfuscated.
978../folder                    // Names in all the files under the folder directory and its subdirectories are not obfuscated.
979../oh_modules/json5          // Names in all the files in the imported third-party library json5 are not obfuscated.
980```
981
982**How to retain remote HAR packages in modules?**
983
984**Method 1**: Specify the exact path of the remote HAR package in the module-level oh_modules. This path is a symbolic link to the real path in the project-level oh_modules. When configuring the path in the module-level oh_modules as a trustlist, you should specify the bundle name or a directory following the bundle name to correctly link to the real directory path. Therefore, configuring only the parent directory name of the HAR package is not supported.
985
986```
987// Positive example:
988-keep
989./oh_modules/harName1         // Names in all the files under the harName1 directory and its subdirectories are not obfuscated.
990./oh_modules/harName1/src     // Names in all the files under the src directory and its subdirectories are not obfuscated.
991./oh_modules/folder/harName2  // Names in all the files under the harName2 directory and its subdirectories are not obfuscated.
992
993// Negative example:
994-keep
995./oh_modules                  // To retain the HAR package in the module-level oh_modules, configuring the parent directory name of the HAR package is not supported.
996```
997
998**Method 2**: Specify the exact path of the remote HAR package in the project-level oh_modules. Since the file paths in the project-level oh_modules are all real paths, any path can be configured.
999
1000```
1001-keep
1002../oh_modules                  // Names in all the files under the project-level oh_modules and its subdirectories are not obfuscated.
1003../oh_modules/harName3          // Names in all the files under the harName3 directory and its subdirectories are not obfuscated.
1004```
1005
1006The following figure shows the directory structure of module-level oh_moudles and project-level oh_modules in DevEco Studio.
1007
1008![oh_modules](./figures/oh_modules.png)
1009
1010**NOTE**
1011
1012**1.** For files retained by **-keep filepath**, all exported names and their properties in the dependency chain of these files are also retained.
1013
1014**2.** This option does not affect the capability provided by the **-enable-filename-obfuscation** option.
1015
1016### Wildcards Supported by Retention Options
1017
1018#### Name Wildcards
1019
1020The table below lists the name wildcards supported.
1021
1022| Wildcard| Description                  | Example                                      |
1023| ------ | ---------------------- | ------------------------------------------ |
1024| ?      | Matches any single character.      | "AB?" matches "ABC", but not "AB".        |
1025| \*     | Matches any number of characters.| "\*AB\*" matches "AB", "aABb", "cAB", and "ABc".|
1026
1027**Use Example**
1028
1029Retain all property names that start with **a**.
1030
1031```
1032-keep-property-name
1033a*
1034```
1035
1036Retain all single-character property names.
1037
1038```
1039-keep-property-name
1040?
1041```
1042
1043Retain all property names.
1044
1045```
1046-keep-property-name
1047*
1048```
1049
1050#### Path Wildcards
1051
1052The table below lists the path wildcards supported.
1053
1054| Wildcard| Description                                                                    | Example                                             |
1055| ------ | ------------------------------------------------------------------------ | ------------------------------------------------- |
1056| ?     | Matches any single character except the path separator (/).                                     | "../a?" matches "../ab", but not "../a/".        |
1057| \*      | Matches any number of characters except the path separator (/).                               | "../a*/c" matches "../ab/c", but not "../ab/d/s/c".|
1058| \*\*   | Matches any number of characters.                                                  | "../a**/c" matches "../ab/c" and "../ab/d/s/c". |
1059| !      | 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".          |
1060
1061**Use Example**
1062
1063Retain the **c.ets** file in the **../a/b/** directory (excluding subdirectories).
1064
1065```
1066-keep
1067../a/b/*/c.ets
1068```
1069
1070Retain the **c.ets** file in the **../a/b/** directory and its subdirectories.
1071
1072```
1073-keep
1074../a/b/**/c.ets
1075```
1076
1077Retain 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.
1078
1079```
1080-keep
1081../a/b/
1082!../a/b/c.ets
1083```
1084
1085Retain all the files in the **../a/** directory (excluding subdirectories).
1086
1087```
1088-keep
1089../a/*
1090```
1091
1092Retain all the files in the **../a/** directory and its subdirectories.
1093
1094```
1095-keep
1096../a/**
1097```
1098
1099Retain all the files in the module.
1100
1101```
1102-keep
1103./**
1104```
1105
1106**NOTE**
1107
1108**1.** In these options, the wildcards *, ?, and ! cannot be used for other meanings.
1109Example:
1110
1111```
1112class A {
1113  '*'= 1
1114}
1115
1116-keep-property-name
1117*
1118```
1119
1120In this example, * indicates any number of characters, and all property names are retained (not obfuscated). It does not mean that only the * property is retained.
1121
1122**2.** In the **-keep** option, only the path format / is allowed. The path format \ or \\ is not.
1123
1124## Obfuscation Rule Merging Strategies
1125
1126During module compilation, the effective obfuscation rules are the merged result of the current module's obfuscation rules and the dependent modules' obfuscation rules. The specific rules are as follows:
1127
1128**Obfuscation rules of the current module**
1129Content of the obfuscation configuration file specified by the **arkOptions.obfuscation.ruleOptions.files** field in the current module's configuration file **build-profile.json5**.
1130
1131**Obfuscation rules of dependent modules**
1132Depending on the type of dependent module, the obfuscation rules come from the following two sources:
1133
1134- **Local HAR/HSP modules**
1135  Content of the obfuscation configuration file specified by the **arkOptions.obfuscation.consumerFiles** field in the module's configuration file **build-profile.json5**.
1136
1137- **Remote HAR/HSP packages**
1138  Content of the **obfuscation.txt** file in the remote HAR/HSP package.
1139
1140If an HAP, HSP, or HAR is built, the final obfuscation rules are the merge of the following files:
1141* **ruleOptions.files** attribute of the current module
1142* **consumerFiles** attribute of the dependent local HSP
1143* **consumerFiles** attribute of the dependent local HAR
1144* **obfuscation.txt** files in the dependent remote HAR and remote HSP
1145
1146If an HAR is built, the **obfuscation.txt** file in the generated remote HAR is the merge of the following files:
1147* Its own **consumerFiles** attribute
1148* **consumerFiles** attribute of the dependent local HSP
1149* **consumerFiles** attribute of the dependent local HAR
1150* **obfuscation.txt** files in the dependent remote HAR and remote HSP
1151
1152If an HSP is built, the **obfuscation.txt** file in the generated remote HSP only contains its own **consumerFiles** attribute.
1153If a HAP is built, no **obfuscation.txt** will be generated.
1154
1155#### Obfuscation Rule Merging Logic
1156
1157Obfuscation options: The OR operation is used for merging. If a switch option exists in any of the rule files being merged, it will be included in the final merged result.
1158Retention options: When merging, for trustlist options, their content is the union of all.
1159
1160- If the current module's obfuscation configuration does not include the **-enable-lib-obfuscation-options** option, the merged result is the current module's obfuscation rules and the [retention options](#retention-options) in the dependent modules' obfuscation rules.
1161
1162- If the current module's obfuscation configuration includes the **-enable-lib-obfuscation-options** option, the merged result is the current module's obfuscation rules and the dependent modules' obfuscation rules.
1163
1164When the obfuscation configuration file specified by **consumerFiles** contains the following obfuscation rules, these rules will be merged into the **obfuscation.txt** file of a remote HAR or remote HSP, whereas other obfuscation rules will not.
1165```
1166// Obfuscation options
1167-enable-property-obfuscation
1168-enable-string-property-obfuscation
1169-enable-toplevel-obfuscation
1170-compact
1171-remove-log
1172
1173// Retention options
1174-keep-property-name
1175-keep-global-name
1176```
1177
1178**Precautions for Obfuscation in HSP and HAR**
1179
11801. If the obfuscation configuration file specified by **consumerFiles** contains the above obfuscation options, when other modules depend on this module, these obfuscation options will be merged with the main module's obfuscation rules, thereby affecting the main module. Therefore, you are not advised to configure obfuscation options in the **consumer-rules.txt** file. Instead, configure only retention options in the file.
1181
11822. 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**.
1183
1184## Mappings Between Obfuscation Options and Minimum SDK Versions
1185
1186| Obfuscation Option| Description | Minimum SDK Version|
1187| ------- | --------- | ------ |
1188| -disable-obfuscation         | Disables obfuscation.| 4.0.9.2 |
1189| -enable-property-obfuscation | Enables property name obfuscation.| 4.0.9.2 |
1190| -enable-string-property-obfuscation | Enables obfuscation for string literal property names.| 4.0.9.2 |
1191| -enable-toplevel-obfuscation | Enables top-level scope name obfuscation.| 4.0.9.2 |
1192| -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 |
1193| -enable-export-obfuscation   | Enables obfuscation for imported/exported names.| 4.1.5.3 |
1194| -compact                     | Removes unnecessary spaces and all line feeds.| 4.0.9.2 |
1195| -remove-log                  | Removes the expressions involving direct calls to the console. statement in specific scenarios.| 4.0.9.2 |
1196| -print-namecache             | Saves the name cache to the specified file path.| 4.0.9.2 |
1197| -apply-namecache             | Reuses the specified name cache file.| 4.0.9.2 |
1198| -remove-comments             | Removes all comments in the file.| 4.1.5.3 |
1199| -keep-property-name          | Retains property names.| 4.0.9.2 |
1200| -keep-global-name            | Retains top-level scope names.| 4.0.9.2 |
1201| -keep-file-name              | Retains file or folder names in the HAR.<br> Retains file or folder names in the HAP/HSP.| 4.1.5.3 <br> 5.0.0.19 |
1202| -keep-dts                    | Retains the names in the .d.ts file in the specified path.| 4.0.9.2 |
1203| -keep-comments               | Retains the classes, functions, namespaces, enums, structs, interfaces, modules, types, and JsDoc comments above properties in the declaration file generated after compilation.| 4.1.5.3 |
1204| -keep                        | Retains all names in the specified path.| 5.0.0.18 |
1205| Wildcard                      | The retention options of the name classes and path classes support wildcards.| 5.0.0.24 |
1206| -use-keep-in-source          | Marks trustlists in source code by comments.| 5.1.0.57 |
1207