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