• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Arkguard
2Arkguard is a javascript and typescript obfuscation tool.
3For Chinese version please read [README-cn.md](README-cn.md)
4(中文版说明请查看[README-cn.md](README-cn.md)).
5
6# Usage in DevEco Studio
7Arkguard has been integrated into SDK. It is convenient to use Arkguard in DevEco Studio.
8In DevEco Studio, Arkguard can be enabled only in Stage Model (FA Model is not supported).
9For now only name obfuscations can be used in DevEco Studio (because other obfuscation
10abilities of Arkguard may hurt execution performance).
11You can obfuscate the following names:
12* parameter names and local variable names
13* names in global scope
14* property names
15
16We enable the obfuscation of parameter names and local variable names by default. However,
17global names obfuscation and property names obfuscation are disabled by default, as they may
18cause runtime error if they are enabled by default.
19You can enable them by [obfuscation options](#obfuscation-options).
20
21When you create a new project, the following config will be generated in `build-profile.json5`.
22```
23"arkOptions": {
24  "obfuscation": {
25    "ruleOptions": {
26      "enable": true,
27      "files": ["obfuscation-rules.txt"],
28    }
29  }
30}
31```
32When you create a new library, additional property `consumerFiles` will be added.
33```
34"arkOptions": {
35  "obfuscation": {
36    "ruleOptions": {
37      "enable": true,
38      "files": ["obfuscation-rules.txt"],
39    }
40    "consumerFiles": ["consumer-rules.txt"]
41  }
42}
43```
44
45To enable obfuscation, the following conditions should be satisfied:
46* the property `ruleOptions.enable` is `true` and the property `ruleOptions.enable` of every dependent library is `true`.
47* build in release mode
48
49The files in the property `ruleOptions.files` will be applied when you build HAP or HAR.
50
51The files in the property `consumerFiles` will be applied when you build the project or library which
52depends on this library. They will also be merged into a file `obfuscation.txt` in the resulting HAR.
53
54When you are building HAP or HAR, the final obfucation rules are combination of self's `ruleOptions.files`
55property, dependent libraries' `consumerFiles` properties and dependent HAR's `obfuscation.txt`.
56If you are building HAR, the content of `obfuscation.txt` is the combination of self's `consumerFiles` property,
57dependent libraries' `consumerFiles` properties and dependent HAR's `obfuscation.txt`. If you are building
58HAP, `obfuscation.txt` will not be generated. For more details, please jump to
59"[How Arkguard merges rules](#how-arkguard-merges-rules)".
60
61## Write rules
62
63The files `obfuscation-rules.txt` and `consumer-rules.txt` are created by DevEco Studio automatically, but they do not
64contain any rule by default. You can write rules in these files or include rules from other files, as the following
65example shows.
66```
67"buildOption": {
68  "arkOptions": {
69    "obfuscation": {
70      "ruleOptions": {
71        "enable": true,
72        "files": ["obfuscation-rules.txt", "myrules.txt"],
73      }
74      "consumerFiles": ["consumer-rules.txt", "my-consumer-rules.txt"]
75    }
76  }
77}
78```
79
80In rule files, you can write [obfuscation options](#obfuscation-options) and [keep options](#keep-options).
81
82### Obfuscation options
83
84`-disable-obfuscation`
85
86Specifies to disable all obfuscations. If you use this option, the resulting HAP or HAR will not be obfuscated. By default,
87Arkguard only obfuscates the parameter names and local variable names by assigning random short names to them.
88
89`-enable-property-obfuscation`
90
91Specifies to obfuscate the property names. If you use this option, all property names will be obfuscated except the
92following:
93* the property names of classes or objects directly imported or exported by `import/export` will be kept. For example, the property name `data` in
94    ```
95    export class MyClass {
96       data: string;
97    }
98    ```
99    will not be obfuscated.
100For 'indirectly export' cases such as `export MyClass` and `let a = MyClass; export {a};`, if you do not want to obfuscate
101their property names, you need to use [keep options](#keep-options) to keep them. Besides, for the property names of properties of directly exported classes or objects, like `name` and `age` in the following example, if you do not want to obfuscate them, then you also need [keep options](#keep-options) to keep them.
102    ```
103    export class MyClass {
104       person = {name: "123", age: 100};
105    }
106    ```
107* the property names defined in UI components. For example, the property names `message` and `data` in
108    ```
109    @Component struct MyExample {
110        @State message: string = "hello";
111        data: number[] = [];
112        ...
113    }
114    ```
115    will not be obfuscated.
116* the property names that are specified by [keep options](#keep-options).
117* the property names in system API list. System API list is a name set which is extracted from SDK automatically by default. The cache file is systemApiCache.json, and the path is build/cache/{...}/release/obfuscation in the module directory.
118* in the Native API scenario, the APIs in the d.ts file of so library will not be obfuscated.
119* the property names that are string literals. For example, the property names "name" and "age" in the following code will not be obfuscated.
120    ```
121    let person = {"name": "abc"};
122    person["age"] = 22;
123    ```
124    If you want to obfuscate these string literal property names, you should addtionally use the option `-enable-toplevel-obfuscation`. For example,
125    ```
126    -enable-property-obfuscation
127    -enable-string-property-obfuscation
128    ```
129    **Note**:
130    **1.** If there are string literal property names which contain special characters (that is, all characters except
131    `a-z, A-Z, 0-9, _`, for example `let obj = {"\n": 123, "": 4, " ": 5}` then we would not suggest to enable the
132    option `-enable-string-property-obfuscation`, because [keep options](#keep-options) may not allow to keep these
133    names when you do not want to obfuscate them.
134    **2.** The property white list of the system API does not include the string constant in the declaration file. For example, the string `'ohos.want.action.home'` in the example is not included in the white list.
135    ```
136    // System Api @ohos.app.ability.wantConstant snippet:
137    export enum Params {
138      DLP_PARAM_SANDBOX = 'ohos.dlp.param.sandbox'
139    }
140    // Developer source example:
141    let params = obj['ohos.want.action.home'];
142    ```
143    Therefore, when `-enable-string-property-obfuscation` is enabled, if you don't want to obfuscate the property like `'ohos.dlp.param.sandbox'`, which is a string constant in system api. you should keep it manually.
144
145Specifies to obfuscate the names in the global scope. If you use this option, all global names will be obfuscated
146except the following:
147* the `import/export` global names.
148* the global names that are not declared in the current file.
149* the global names that are specified by [keep options](#keep-options).
150* the global names in system API list.
151
152`-enable-filename-obfuscation`
153
154Specifies to obfuscate the file/folder names. This option only takes effect in OpenHarmony Archive(HAR) scenarios. If you use this option, all file/folder names will be obfuscated except the following:
155* the file/folder names configured in the 'main' and 'types' fields in the oh-package.json5.
156* the file/folder names configured in the 'srcEntry' field in the module.json5.
157* the file/folder names that are specified by [keep options](#keep-file-name-link).
158* non-ECMAScript module reference (ECMAScript module example: `import {foo} from './filename'`)
159* non-path reference, such as json5 will not be obfuscated `import module from 'json5'`
160
161`-compact`
162
163Specifies to remove unnecessary blank spaces and all line feeds. If you use this option, all code will be compressed into
164one line.
165**Note**: The stack information in release mode only includes the line number of code, not the column number. Therefore, when the compact is enabled, the specific location of the source code cannot be located based on the line number of stack information.
166
167`-remove-log`
168
169Delete the expressions involving direct calls to console.* statements in the following scenarios:
1701. Calls at the toplevel level of a file.
1712. Calls within a block.
1723. Calls within a module.
1734. Calls within a switch statement.
174and the return value of console.* should not be called
175
176`-print-namecache` filepath
177
178Specifies to print the name cache that contains the mapping from the old names to new names.
179Note: The namecache.json file will be generated every time the module is fully built, so you should save a copy each time you publish a new version.
180
181`-apply-namecache` filepath
182
183Specifies to reuse the given cache file. The old names in the cache will receive the corresponding new names specified in
184the cache. Other names will receive new random short names. This option should be used in incremental obfuscation.
185
186By default, DevEco Studio will keep and update the namecache file in the temporary cache directory and apply the cache for
187incremental compilation.
188Cache directory: build/cache/{...}/release/obfuscation
189
190`-remove-comments`
191
192Remove all comments including single line, multi line and JsDoc comments, in a project except:
193* Those names of JsDoc comments above class, function, struct, enum ... in declaration files are in `-keep-comments`.
194**Note**: `-keep-comments` doesn't work for comments in generated source files, which will be deleted.
195### Keep options
196
197#### `-keep-property-name` [,identifiers,...]
198
199Specifies property names that you want to keep. For example,
200```
201-keep-property-name
202age
203firstName
204lastName
205```
206**Note**: This option is avaliable when `-enable-property-obfuscation` is enabled.
207
208`-keep-comments`
209To retain JsDoc comments above elements in declaration files, such as preserving the JsDoc comment above the Human class,
210you can make the following configuration:
211```
212-keep-comments
213Human
214```
215**Note**:
2161. This option is avaliable when `-remove-comments` is enabled.
2172. If the name of an element is obfuscated, the JsDoc comments
218above that element cannot be kept using `-keep-comments`. For example, when you have exportClass in `-keep-comments`,
219you should make sure that the following class will not be obfuscated, or the JsDoc comments above the class will still be removed:
220```
221/**
222** @class exportClass
223*/
224export class exportClass {}
225```
226
227**What property names should be kept?**
228
229For safety, we would suggest keeping all property names that are not accessed through dot syntax.
230
231Example:
232```
233var obj = {x0: 0, x1: 0, x2: 0};
234for (var i = 0; i <= 2; i++) {
235  console.log(obj['x' + i]);  // x0, x1, x2 should be kept
236}
237
238Object.defineProperty(obj, 'y', {});  // y should be kept
239console.log(obj.y);
240
241obj.s = 0;
242let key = 's';
243console.log(obj[key]);        // s should be kept
244
245obj.u = 0;
246console.log(obj.u);           // u can be safely obfuscated
247
248obj.t = 0;
249console.log(obj['t']);        // t and 't' can be safely obfuscated when `-enable-string-property-obfuscation`, but we suggest keeping t
250
251obj['v'] = 0;
252console.log(obj['v']);        // 'v' can be safely obfuscated when `-enable-string-property-obfuscation`, but we suggest keeping v
253```
254In the native API scenario, if in the ets/ts/js file you want to use APIs that are not declared in d.ts file, you need to keep these APIs.
255
256`-keep-global-name` [,identifiers,...]
257
258Specifies names that you want to keep in the global scope. For example,
259```
260-keep-global-name
261Person
262printPersonName
263```
264
265**What global names should be kept?**
266
267It is known that in javascript the variables in the global scope are properties of `globalThis`. So if in your code
268you access a global variable as a property, then the global name should be kept.
269
270Example:
271```
272var a = 0;
273console.log(globalThis.a);  // a should be kept
274
275function foo(){}
276globalThis.foo();           // foo should be kept
277
278var c = 0;
279console.log(c);             // c can be safely obfuscated
280
281function bar(){}
282bar();                      // bar can be safely obfuscated
283
284class MyClass {}
285let d = new MyClass();      // MyClass can be safely obfuscated
286```
287
288<a id="keep-file-name-link">`-keep-file-name` [,identifiers,...]</a>
289
290Specify the name of files/folders to keep (no need to write the file suffix). for example,
291```
292-keep-file-name
293index
294entry
295```
296**What file names should be kept?**
297```
298const module1 = require('./file1')   // ARKTs doesn't support CommonJS, this path reference should be kept.
299const moduleName = './file2'
300const module2 = import(moduleName)   // dynamic reference cannot identify whether moduleName is a path and should be retained.
301```
302
303`-keep-dts` filepath
304
305Specifies to keep names in the given `.d.ts` file. Here filepath can be also a directory. If so, then the names in all
306`d.ts` files under the given directory will be kept.
307If your are building HAR with this option, then the kept names will be merged into the resulting `obfuscation.txt`.
308
309### Comments
310
311You can write comments in obfuscation rule file by using `#`. The line begins with `#` is treated as comment.
312For example,
313```
314# white list for MainAbility.ets
315-keep-global-name
316MyComponent
317GlobalFunction
318
319-keep-property-name # white list for dynamic property names
320firstName
321lastName
322age
323```
324If your are building HAR, comments will not be merged into the resulting `obfuscation.txt`.
325
326### How Arkguard merges rules
327Typically there may be serveral rule files in your project. These rule files come from:
328* `ruleOptions.files` in main project (Here by main project we mean the project you are building)
329* `consumerFiles` in local dependent libraries
330* `obfuscate.txt` in remote dependent HARs
331When building your main project, all these rules will be merged by the following strategy (in pseudo code):
332```
333let `listRules` be the list of all rule files that are mentioned above.
334let finalRule = {
335    disableObfuscation: false,
336    enablePropertyObfuscation: false,
337    enableToplevelObfuscation: false,
338    compact: false,
339    removeLog: false,
340    keepPropertyName: [],
341    keepGlobalName: [],
342    keepDts: [],
343    printNamecache: string,
344    applyNamecache: string
345}
346for each file in `listRules`:
347    for each option in file:
348        switch(option) {
349            case -disable-obfuscation:
350                finalRule.disableObfuscation = true;
351                continue;
352            case -enable-property-obfuscation:
353                finalRule.enablePropertyObfuscation = true;
354                continue;
355            case -enable-toplevel-obfuscation:
356                finalRule.enableToplevelObfuscation = true;
357                continue;
358            case -compact:
359                finalRule.compact = true;
360                continue;
361            case -remove-log:
362                finalRule.removeLog = true;
363                continue;
364            case -print-namecache:
365                finalRule.printNamecache = #{specified path};
366                continue;
367            case -apply-namecache:
368                finalRule.applyNamecache = #{specified path};
369                continue;
370            case -keep-property-name:
371                finalRule.keepPropertyName.push(#{specified names});
372                continue;
373            case -keep-global-name:
374                finalRule.keepGlobalName.push(#{specified names});
375                continue;
376            case -keep-dts:
377                finalRule.keepDts.push(#{specified file path});
378                continue;
379        }
380    end-for
381end-for
382```
383The final obfuscation rules are in the object `finalRule`.
384
385If you are building HAR, the resulting `obfuscate.txt` are obtained by merging the rules from `consumerFiles` in main
386project and local dependent libraries, and `obfuscate.txt` in remote dependent HARs. The merging strategy is the same
387except:
388* The `-keep-dts` option will be converted to `-keep-global-name` and `-keep-property-name` options in the resulting
389`obfuscate.txt`.
390* The options `-print-namecache` and `apply-namecache` will be omitted and will not appear in the resulting
391`obfuscate.txt`.
392