• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ArkGuard Principles and Capabilities for Bytecode 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 function names, class names, file names, and other identifiers to meaningless names.|
16
17## Obfuscation Scope
18
19### Supported Languages
20
21ArkGuard supports the ArkTS/TS/JS languages. For JSON, only filename obfuscation is supported. It does not support C/C++ or resource files.
22
23### Obfuscation Capabilities
24
25ArkGuard provides basic name obfuscation, but does not support advanced features like control obfuscation or data obfuscation.
26
27It primarily offers name renaming and trustlist configuration for retention.
28
29### Limitations of Obfuscation Capabilities
30
31**Language Limitations**
32
33Code 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.
34
35In 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.
36
37As 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.
38
39To illustrate, consider this example:
40
41Assume 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.
42
43```typescript
44// Before obfuscation:
45class A1 {
46  prop1: string = '';
47}
48class A2 {
49  prop1: string = '';
50}
51function test(input: A1) {
52  console.log(input.prop1);
53}
54let a2 = new A2();
55a2.prop1 = 'prop a2';
56test(a2);
57```
58
59```typescript
60// After obfuscation:
61class A1 {
62  prop1: string = '';
63}
64class A2 {
65  a: string = '';
66}
67function test(input: A1) {
68  console.log(input.prop1);
69}
70let a2 = new A2();
71a2.a = 'prop a2';
72test(a2);
73```
74
75You should be aware of these differences and use unique names to achieve better obfuscation results.
76
77**Limited security assurance**
78
79Like other obfuscation tools, ArkGuard increases reverse engineering difficulty but cannot prevent it entirely.
80
81You 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 third-party hardening measures.
82
83## Obfuscation Mechanism and Process
84
85The following figure shows a simplified compilation process.
86
87![bytecode-compilation-process](figures/bytecode-compilation-process.png)
88
89You can enable the obfuscation feature in the **build-profile.json5** file of the module so that the .abc files can be automatically obfuscated during compilation and packaging. For details, see [Using ArkGuard for Bytecode Obfuscation](bytecode-obfuscation-guide.md).
90
91During 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 bytecode obfuscation to .abc files generated, and writes the obfuscated files to the **build** directory. You can verify the obfuscation effect by examining the output in the **build** directory.
92
93Before using obfuscation, you are advised to learn about the capabilities of [obfuscation options](#obfuscation-options) and [retention options](#retention-options), and select the appropriate capabilities for your needs.
94
95## Obfuscation Options
96
97### Summary of Existing Obfuscation Options
98
99| Function| Option|
100| --- | --- |
101|Disabling obfuscation|[`-disable-obfuscation`](#-disable-obfuscation)|
102|Obfuscating property names|[`-enable-property-obfuscation`](#-enable-property-obfuscation)|
103|Obfuscating string literal property names|[`-enable-string-property-obfuscation`](#-enable-string-property-obfuscation)|
104|Obfuscating top-level scope names|[`-enable-toplevel-obfuscation`](#-enable-toplevel-obfuscation)|
105|Obfuscating imported/exported names|[`-enable-export-obfuscation`](#-enable-export-obfuscation)|
106|Obfuscating file names|[`-enable-filename-obfuscation`](#-enable-filename-obfuscation)|
107|Compressing code|[`-compact`](#-compact)|
108|Removing console logs|[`-remove-log`](#-remove-log)|
109|Printing name caches|[`-print-namecache`](#-print-namecache)|
110|Reusing name caches|[`-apply-namecache`](#-apply-namecache)|
111|Enabling bytecode obfuscation|[`-enable-bytecode-obfuscation`](#-enable-bytecode-obfuscation)|
112|Enabling bytecode obfuscation debugging|[`-enable-bytecode-obfuscation-debugging`](#-enable-bytecode-obfuscation-debugging)|
113
114### -disable-obfuscation
115
116Disables code obfuscation.
117
118If this option is configured, the default obfuscation capabilities and all configured obfuscation and retention options become invalid. This has the same effect as disabling obfuscation in the module's **build-profile.json5** file.
119
120### -enable-property-obfuscation
121
122Enables property name obfuscation. The effect is as follows:
123
124 ```ts
125// Before obfuscation:
126class TestA {
127  static prop1: number = 0;
128}
129TestA.prop1;
130 ```
131
132 ```ts
133// After obfuscation:
134class TestA {
135  static i: number = 0;
136}
137TestA.i;
138 ```
139
140If this option is configured, all property names except the following are obfuscated:
141
142* 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 enabled. For example, the property name **data** in the following example is not obfuscated.
143
144    ```ts
145    export class MyClass {
146       data: string;
147    }
148    ```
149
150* Property names in ArkUI components. For example, **message** and **data** in the following example are not obfuscated.
151
152    ```ts
153    @Component struct MyExample {
154     @State message: string = "hello";
155        data: number[] = [];
156        // ...
157    }
158    ```
159
160* Property names specified in [retention options](#-keep-property-name).
161* 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.
162* String literal property names. For example, **firstName** and **personAge** in the following example are not obfuscated.
163
164    ```ts
165    let person = {"firstName": "abc"};
166    person["personAge"] = 22;
167    ```
168
169* Annotation member names. For example, **authorName** and **revision** in the following example are not obfuscated.
170
171    ```ts
172    @interface MyAnnotation {
173    authorName: string;
174    revision: number = 1;
175    }
176    ```
177
178### -enable-string-property-obfuscation
179
180Enables obfuscation of string literal property names. It is effective only if property name obfuscation is enabled.
181
182To obfuscate string literal property names, you must use this option together with **-enable-property-obfuscation**. Example:
183
184  ```txt
185  -enable-property-obfuscation
186  -enable-string-property-obfuscation
187  ```
188
189According to the preceding configuration, the obfuscation effect of **"fritstName"** and **"personAge"** is as follows:
190
191  ```ts
192  // Before obfuscation:
193  let person = {"fritstName": "abc"};
194  person["personAge"] = 22;
195  ```
196
197  ```ts
198  // After obfuscation:
199  let person = {"a": "abc"};
200  person["b"] = 22;
201  ```
202
203**NOTE**
204
205**1.** If a string literal property name 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 (_).
206
207**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.
208
209```ts
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 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```ts
225// Before obfuscation:
226let count = 0;
227```
228
229```ts
230// After obfuscation:
231let 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** in case that the **-enable-export-obfuscation** option is not enabled.
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```ts
246// Before obfuscation:
247namespace ns {
248  export type customT = string;
249}
250```
251
252```ts
253// After obfuscation:
254namespace 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.
260
261To obfuscate names imported/exported in the top-level scope, use this option with **-enable-toplevel-obfuscation**.
262
263To obfuscate imported or exported property names, use this option with **-enable-property-obfuscation**. Note the following special scenarios:
264
265* Names exported from remote HARs (packages whose real paths are in **oh_modules**) and their property names are not obfuscated.
266* Names and property names specified by [retention options](#retention-options) are not obfuscated.
267* Names in the SDK API list are not obfuscated.
268
269### -enable-filename-obfuscation
270
271Enables obfuscation of file/folder names. The effect is as follows:
272
273```ts
274// Before obfuscation:
275import * as m from '../test1/test2';
276import { foo } from '../test1/test2';
277const module = import('../test1/test2');
278```
279
280```ts
281// After obfuscation:
282import * as m from '../a/b';
283import { foo } from '../a/b';
284const module = import('../a/b');
285```
286
287If this option is configured, all file/folder names except the following are obfuscated:
288
289* File or folder names specified by the **main** and **types** fields in the **oh-package.json5** file.
290* File or folder names specified by the **srcEntry** field in the **module.json5** file of the module.
291* File or folder names specified by [-keep-file-name](#-keep-file-name).
292* File or folder names in non-ECMAScript module reference mode (for example, const module = require('./module')).
293* File or folder names in non-path reference mode. For example, **json5** in the example **import module from 'json5'** is not obfuscated.
294
295> **NOTE**
296>
297> 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.
298>
299> 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.
300
301### -compact
302
303Removes unnecessary spaces and all line feeds.
304
305If this option is configured, all code is compressed to one line. The effect is as follows:
306
307```ts
308// Before obfuscation:
309class TestA {
310  static prop1: number = 0;
311}
312TestA.prop1;
313```
314
315```ts
316// After obfuscation:
317class TestA { static prop1: number = 0; } TestA.prop1;
318```
319
320> **NOTE**
321>
322> 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.
323
324### -remove-log
325
326Removes calls to console.* statements, provided the return value is not used. The effect is as follows:
327
328```ts
329// Before obfuscation:
330if (flag) {
331  console.log("hello");
332}
333```
334
335```ts
336// After obfuscation:
337if (flag) {
338}
339```
340
341If this option is configured, the console.* statements in the following scenarios are removed:
342
3431. Calls at the top layer of a file.
344    Example:
345
346    ```js
347    console.log("in tolevel");
348    ```
349
3502. Calls within a code block.
351    Example:
352
353    ```ts
354    function foo() {
355    console.log('in block');
356    }
357    ```
358
3593. Calls with a module or namespace.
360    Example:
361
362    ```ts
363    namespace ns {
364    console.log('in ns');
365    }
366    ```
367
3684. Calls within a **switch** statement.
369    Example:
370
371    ```js
372    switch (value) {
373    case 1:
374        console.log("in switch case");
375        break;
376    default:
377        console.warn("default");
378    }
379    ```
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```txt
388-print-namecache
389./customCache/nameCache.json
390```
391
392> **NOTE**
393>
394> 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.
395
396### -apply-namecache
397
398Reuses 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.
399
400This 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.
401
402Example:
403
404```txt
405-apply-namecache
406./customCache/nameCache.json
407```
408
409By default, DevEco Studio saves cache files in a temporary cache directory and automatically applies the cache files during incremental build.
410
411Default cache directory: **build/default/cache/{...}/release/obfuscation**
412
413### -enable-lib-obfuscation-options
414
415Merges obfuscation options of dependent modules into the obfuscation configuration of the current module.
416
417Obfuscation configuration includes [obfuscation options](#obfuscation-options) and [retention options](#retention-options).
418
419By default, the effective obfuscation configuration is the merged result of the current module's obfuscation configuration and the dependent modules' retention options.
420
421When 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.
422
423For details about the merging logic, see [Obfuscation Rule Merging Strategies](#obfuscation-rule-merging-strategies).
424
425### -enable-bytecode-obfuscation
426
427Enables or disables bytecode obfuscation. This function is disabled by default.
428
429### -enable-bytecode-obfuscation-debugging
430
431Controls whether bytecode obfuscation outputs debugging information. If this option is enabled, obfuscation logs are generated. For details, see [Viewing Obfuscation Effects](bytecode-obfuscation-guide.md#viewing-obfuscation-effects). This option is not enabled by default.
432
433Use this option with **-enable-bytecode-obfuscation**.
434
435## Retention Options
436
437### Summary of Existing Retention Options
438
439|Function|Option|
440|-----|-----|
441|Retaining specified property names|[-keep-property-name](#-keep-property-name)|
442|Retaining specified top-level scope names or imported/exported element names|[-keep-global-name](#-keep-global-name)|
443|Retaining specified file/folder names|[-keep-file-name](#-keep-file-name)|
444|Retaining all names in specified declaration files|[-keep-dts](#-keep-dts)|
445|Retaining all names in specified source code files|[-keep](#-keep)|
446
447### -keep-property-name
448
449Retains the specified property names. [Name wildcards](#name-wildcards) are supported. The following configuration is used to retain properties named **age**, **firstName**, and **lastName**:
450
451```txt
452-keep-property-name
453age
454firstName
455lastName
456```
457
458**NOTE**
459
460**1.** This option takes effect when **-enable-property-obfuscation** is used.
461
462**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**.
463
464**Which property names should be retained?**
465
4661. If object properties are defined via string concatenation, variable access, or the **defineProperty** method within the code, these property names should be retained. Example:
467
468   ```js
469   var obj = {x0: 0, x1: 0, x2: 0};
470   for (var i = 0; i <= 2; i++) {
471       console.info(obj['x' + i]);  // x0, x1, and x2 should be retained.
472   }
473
474   Object.defineProperty(obj, 'y', {});  // y should be retained.
475   Object.getOwnPropertyDescriptor(obj, 'y');  // y should be retained.
476   console.info(obj.y);
477
478   obj.s = 0;
479   let key = 's';
480   console.info(obj[key]);        // The variable value s corresponding to key should be retained.
481
482   obj.t1 = 0;
483   console.info(obj['t' + '1']);        // t1 should be retained.
484   ```
485
486   For the following string literal property calls, you can choose to retain them.
487
488   ```js
489   // Obfuscation configuration:
490   // -enable-property-obfuscation
491   // -enable-string-property-obfuscation
492   obj.t = 0;
493   console.info(obj['t']); // 't' will be correctly confused, and t can be retained.
494
495   obj.['v'] = 0;
496   console.info(obj['v']); // 'v' will be correctly confused, and v can be retained.
497   ```
498
4992. 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 **firstName** and **personAge** in the following example, if you do not want to obfuscate them, use [retention options](#retention-options) to retain them.
500
501   ```ts
502   export class MyClass {
503       person = {firstName: "123", personAge: 100};
504   }
505   ```
506
5073. If you want to use an API (for example, **foo** in the example) of the .so library in the ArkTS/TS/JS file, manually keep the API name.
508
509   ```ts
510   import testNapi from 'library.so'
511   testNapi.foo() // foo should be retained Example: -keep-property-name foo
512   ```
513
5144. Fields used in JSON parsing and object serialization should be retained.
515
516   ```ts
517   // Example JSON file structure (test.json):
518   /*
519   {
520     "jsonProperty": "value",
521     "otherProperty": "value2"
522   }
523   */
524   const jsonData = fs.readFileSync('./test.json', 'utf8');
525   let jsonObj = JSON.parse(jsonData);
526   let jsonProp = jsonObj.jsonProperty; // jsonProperty should be retained.
527   class jsonTest {
528     prop1: string = '';
529     prop2: number = 0
530   }
531   let obj = new jsonTest();
532   const jsonStr = JSON.stringify(obj); // prop1 and prop2 will be obfuscated and should be retained.
533   ```
534
5355. Database-related fields should be manually retained. For example, properties in the database key-value pair type (ValuesBucket):
536
537   ```ts
538   const valueBucket: ValuesBucket = {
539     'ID1': ID1, // ID1 should be retained.
540     'NAME1': name, // NAME1 should be retained.
541     'AGE1': age, // AGE1 should be retained.
542     'SALARY1': salary // SALARY1 should be retained.
543   }
544   ```
545
5466. 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.
547    Example:
548
549      ```ts
550      class A {
551        // 1. Member variable decorator
552        @CustomDecoarter
553        propertyName: string = ""   // propertyName should be retained.
554        // 2. Member method decorator
555        @MethodDecoarter
556        methodName1(){} // methodName1 should be retained.
557        // 3. Method parameter decorator
558        methodName2(@ParamDecorator param: string): void { // methodName2 should be retained.
559        }
560      }
561      ```
562
563### -keep-global-name
564
565Retains the specified top-level scope names or imported/exported element names. [Name wildcards](#name-wildcards) are supported. You can perform the configuration as follows:
566
567```txt
568-keep-global-name
569Person
570printPersonName
571```
572
573Names exported from the namespace can also be retained using the **-keep-global-name** option. The following is an example:
574
575```ts
576export namespace Ns {
577  export const age = 18; // -keep-global-name age: retains variable age.
578  export function myFunc () {}; // -keep-global-name myFunc: retains function myFunc.
579}
580```
581
582> **NOTE**
583>
584> 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**.
585
586**Which top-level scope names should be retained?**
587
5881. 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.
589
590   Example:
591
592   ```ts
593   var a = 0;
594   console.info(globalThis.a);  // a should be retained.
595   function foo(){}
596   globalThis.foo();           // foo should be retained.
597   var c = 0;
598   console.info(c);             // c can be correctly obfuscated.
599   function bar(){}
600   bar();                      // bar can be correctly obfuscated.
601   class MyClass {}
602   let d = new MyClass();      // MyClass can be correctly obfuscated.
603   ```
604
6052. 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.
606
607   ```ts
608   import { testNapi, testNapi1 as myNapi } from 'library.so' // testNapi and testNapi1 should be retained.
609   ```
610
611### -keep-file-name
612
613Retains the file/folder names. You do not need to specify the file name extension. [Name wildcards](#name-wildcards) are supported. Example:
614
615```txt
616-keep-file-name
617index
618entry
619```
620
621**Which file names should be retained?**
6221. 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.
623
624   ```ts
625   const module1 = require('./file1')   // file1 should be retained.
626   ```
627
6282. 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.
629
630   ```ts
631   const moduleName = './file2'         // The path name file2 corresponding to moduleName should be retained.
632   const module2 = import(moduleName)
633   ```
634
6353. 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.
636
637   ```json
638   {
639       "routerMap": [
640         {
641           "name": "PageOne",
642           "pageSourceFile": "src/main/ets/pages/directory/PageOne.ets",  // The path should be retained.
643           "buildFunction": "PageOneBuilder",
644           "data": {
645             "description" : "this is PageOne"
646           }
647         }
648       ]
649     }
650   ```
651
652### -keep-dts
653
654Adds names (such as class names, and property names) in the .d.ets 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.ets files in the directory are retained.
655
656### -keep
657
658Retains all names (such as 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.
659**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.
660
661```txt
662-keep
663./src/main/ets/fileName.ts   // Names in the fileName.ts file are not obfuscated.
664../folder                    // Names in all the files under the folder directory and its subdirectories are not obfuscated.
665../oh_modules/json5          // Names in all the files in the imported third-party library json5 are not obfuscated.
666```
667
668**NOTE**
669
670**1.** For files retained by **-keep filepath**, all exported names and their properties in the dependency chain of these files are also retained.
671
672**2.** This option does not affect the capability provided by the **-enable-filename-obfuscation** option.
673
674## Wildcards Supported by Retention Options
675
676### Name Wildcards
677
678The table below lists the name wildcards supported.
679
680| Wildcard| Description                  | Example                                      |
681| ------ | ---------------------- | ------------------------------------------ |
682|?|Matches any single character.|"AB?" matches "ABC", but not "AB".|
683|*|Matches any number of characters.|"*AB*" matches "AB", "aABb", "cAB", and "ABc".|
684
685**Example**
686
687Retain all property names that start with **a**.
688
689```txt
690-keep-property-name
691a*
692```
693
694Retain all single-character property names.
695
696```txt
697-keep-property-name
698?
699```
700
701Retain all property names.
702
703```txt
704-keep-property-name
705*
706```
707
708### Path Wildcards
709
710The table below lists the path wildcards supported.
711
712| Wildcard| Description                                                                    | Example                                             |
713| ------ | ------------------------------------------------------------------------ | ------------------------------------------------- |
714| ?     | Matches any single character except the path separator (/).                                     | "../a?" matches "../ab", but not "../a/".        |
715| \*      | Matches any number of characters except the path separator (/).                               | "../a*/c" matches "../ab/c", but not "../ab/d/s/c".|
716| \*\*   | Matches any number of characters.                                                  | "../a**/c" matches "../ab/c" and "../ab/d/s/c". |
717| !      | 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".          |
718
719**Example**
720
721Retain the **c.ets** file in the **../a/b/** directory (excluding subdirectories).
722
723```txt
724-keep
725../a/b/*/c.ets
726```
727
728Retain the **c.ets** file in the **../a/b/** directory and its subdirectories.
729
730```txt
731-keep
732../a/b/**/c.ets
733```
734Retain 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.
735
736```txt
737-keep
738../a/b/
739!../a/b/c.ets
740```
741
742Retain all the files in the **../a/** directory (excluding subdirectories).
743
744```txt
745-keep
746../a/*
747```
748
749Retain all the files in the **../a/** directory and its subdirectories.
750
751```txt
752-keep
753../a/**
754```
755
756Retain all the files in the module.
757
758```txt
759-keep
760./**
761```
762
763**NOTE**
764
765**1.** In these options, the wildcards *, ?, and ! cannot be used for other meanings. Example:
766
767```txt
768class A {
769  '*'= 1
770}
771-keep-property-name
772*
773```
774
775In 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.
776
777**2.** In the **-keep** option, only the path format / is allowed. The path format \ or \\ is not.
778
779## Obfuscation Rule Merging Strategies
780
781During module compilation, by default, 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:
782
783**Obfuscation rules of the current module**
784
785Content of the obfuscation configuration file specified by the **arkOptions.obfuscation.ruleOptions.files** field in the current module's configuration file **build-profile.json5**.
786
787**Obfuscation rules of dependent modules**
788
789Depending on the type of dependent module, the obfuscation rules come from the following two sources:
790
791- **Local HAR/HSP modules**
792  Content of the obfuscation configuration file specified by the **arkOptions.obfuscation.consumerFiles** field in the module's configuration file **build-profile.json5**.
793
794- **Remote HAR/HSP packages**
795  Content of the **obfuscation.txt** file in the remote HAR/HSP package.
796
797If an HAP, HSP, or HAR is built, the final obfuscation rules are the merge of the following files:
798
799* **ruleOptions.files** attribute of the current module
800* **consumerFiles** attribute of the dependent local HSP
801* **consumerFiles** attribute of the dependent local HAR
802* **obfuscation.txt** files in the dependent remote HAR and remote HSP
803
804If an HAR is built, the **obfuscation.txt** file in the generated remote HAR is the merge of the following files:
805
806* Its own **consumerFiles** attribute
807* **consumerFiles** attribute of the dependent local HSP
808* **consumerFiles** attribute of the dependent local HAR
809* **obfuscation.txt** files in the dependent remote HAR and remote HSP
810
811If an HSP is built, the **obfuscation.txt** file in the generated remote HSP only contains its own **consumerFiles** attribute. If a HAP is built, no **obfuscation.txt** will be generated.
812
813### Obfuscation Rule Merging Logic
814
815Obfuscation 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.
816Retention options: When merging, for trustlist options, their content is the union of all.
817
818- 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.
819
820- 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.
821
822When 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.
823
824```txt
825// Obfuscation options
826-enable-property-obfuscation
827-enable-string-property-obfuscation
828-enable-toplevel-obfuscation
829-remove-log
830// Retention options
831-keep-property-name
832-keep-global-name
833```
834
835**Precautions for Obfuscation in HSP and HAR**
836
8371. 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.
838
8392. 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**.
840