1# Document update instructions 2 3## This document is no longer maintained. Obfuscation documents will be moved to [official guide](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5) and [doc repository](https://gitee.com/openharmony/docs/blob/master/en/application-dev/arkts-utils/source-obfuscation.md) 4 5Note: The source obfuscation is updated synchronously with the DevEco Studio version. It is recommended to read the official guide that comes with the DevEco Studio version first. The community doc repository correspond to the latest open source code, ahead of the source obfuscation function in the released DevEco Studio. 6 7# Arkguard 8 9Arkguard is a javascript and typescript obfuscation tool. 10For Chinese version please read [README-cn.md](README-cn.md) 11(中文版说明请查看[README-cn.md](README-cn.md)). 12 13# Usage in DevEco Studio 14 15Arkguard has been integrated into SDK. It is convenient to use Arkguard in DevEco Studio. 16In DevEco Studio, Arkguard can be enabled only in Stage Model (FA Model is not supported). 17For now only name obfuscations can be used in DevEco Studio (because other obfuscation 18abilities of Arkguard may hurt execution performance). 19You can obfuscate the following names: 20 21* parameter names and local variable names 22* names in global scope 23* property names 24 25We enable the obfuscation of parameter names and local variable names by default. However, 26global names obfuscation and property names obfuscation are disabled by default, as they may 27cause runtime error if they are enabled by default. 28You can enable them by [obfuscation options](#obfuscation-options). 29 30When you create a new project, the following config will be generated in `build-profile.json5`. 31 32``` 33"arkOptions": { 34 "obfuscation": { 35 "ruleOptions": { 36 "enable": true, 37 "files": ["obfuscation-rules.txt"], 38 } 39 } 40} 41``` 42 43When you create a new library, additional property `consumerFiles` will be added. 44 45``` 46"arkOptions": { 47 "obfuscation": { 48 "ruleOptions": { 49 "enable": true, 50 "files": ["obfuscation-rules.txt"], 51 } 52 "consumerFiles": ["consumer-rules.txt"] 53 } 54} 55``` 56 57To enable obfuscation, the following conditions should be satisfied: 58 59* the property `ruleOptions.enable` is `true` and the property `ruleOptions.enable` of every dependent library is `true`. 60* build in release mode 61 62The files in the property `ruleOptions.files` will be applied when you build HAP or HAR. 63 64The files in the property `consumerFiles` will be applied when you build the project or library which 65depends on this library. They will also be merged into a file `obfuscation.txt` in the resulting HAR. 66 67When you are building HAP or HAR, the final obfucation rules are combination of self's `ruleOptions.files` 68property, dependent libraries' `consumerFiles` properties and dependent HAR's `obfuscation.txt`. 69If you are building HAR, the content of `obfuscation.txt` is the combination of self's `consumerFiles` property, 70dependent libraries' `consumerFiles` properties and dependent HAR's `obfuscation.txt`. If you are building 71HAP, `obfuscation.txt` will not be generated. For more details, please jump to 72"[How Arkguard merges rules](#how-arkguard-merges-rules)". 73 74## Write rules 75 76The files `obfuscation-rules.txt` and `consumer-rules.txt` are created by DevEco Studio automatically, but they do not 77contain any rule by default. You can write rules in these files or include rules from other files, as the following 78example shows. 79 80``` 81"buildOption": { 82 "arkOptions": { 83 "obfuscation": { 84 "ruleOptions": { 85 "enable": true, 86 "files": ["obfuscation-rules.txt", "myrules.txt"], 87 } 88 "consumerFiles": ["consumer-rules.txt", "my-consumer-rules.txt"] 89 } 90 } 91} 92``` 93 94In rule files, you can write [obfuscation options](#obfuscation-options) and [keep options](#keep-options). 95 96### Obfuscation options 97 98#### -disable-obfuscation 99 100Specifies to disable all obfuscations. If you use this option, the resulting HAP or HAR will not be obfuscated. By default, 101Arkguard only obfuscates the parameter names and local variable names by assigning random short names to them. 102 103#### -enable-property-obfuscation 104 105Specifies to obfuscate the property names. If you use this option, all property names will be obfuscated except the 106following: 107 108* the property names of classes or objects directly imported or exported by `import/export` will be kept. For example, the property name `data` in 109 110 ``` 111 export class MyClass { 112 data: string; 113 } 114 ``` 115 116 will not be obfuscated. 117For 'indirectly export' cases such as `export MyClass` and `let a = MyClass; export {a};`, if you do not want to obfuscate 118their 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. 119 120 ``` 121 export class MyClass { 122 person = {name: "123", age: 100}; 123 } 124 ``` 125 126 If you want to obfuscate import/export names, please refer to the [`-enable-export-obfuscation`](#-enable-export-obfuscation) option. 127* the property names defined in UI components. For example, the property names `message` and `data` in 128 129 ``` 130 @Component struct MyExample { 131 @State message: string = "hello"; 132 data: number[] = []; 133 ... 134 } 135 ``` 136 137 will not be obfuscated. 138* the property names that are specified by [keep options](#keep-options). 139* 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. 140* in the Native API scenario, the APIs in the d.ts file of so library will not be obfuscated. 141* the property names that are string literals. For example, the property names "name" and "age" in the following code will not be obfuscated. 142 143 ``` 144 let person = {"name": "abc"}; 145 person["age"] = 22; 146 ``` 147 148 If you want to obfuscate these string literal property names, you should addtionally use the option `-enable-toplevel-obfuscation`. For example, 149 150 ``` 151 -enable-property-obfuscation 152 -enable-string-property-obfuscation 153 ``` 154 155 **Note**: 156 **1.** If there are string literal property names which contain special characters (that is, all characters except 157 `a-z, A-Z, 0-9, _`, for example `let obj = {"\n": 123, "": 4, " ": 5}` then we would not suggest to enable the 158 option `-enable-string-property-obfuscation`, because [keep options](#keep-options) may not allow to keep these 159 names when you do not want to obfuscate them. 160 **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. 161 162 ``` 163 // System Api @ohos.app.ability.wantConstant snippet: 164 export enum Params { 165 DLP_PARAM_SANDBOX = 'ohos.dlp.param.sandbox' 166 } 167 // Developer source example: 168 let params = obj['ohos.want.action.home']; 169 ``` 170 171 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. 172 173Specifies to obfuscate the names in the global scope. If you use this option, all global names will be obfuscated 174except the following: 175 176* the `import/export` global names. 177* the global names that are not declared in the current file. 178* the global names that are specified by [keep options](#keep-options). 179* the global names in system API list. 180 181#### -enable-filename-obfuscation 182 183Specifies to obfuscate the file/folder names. If you use this option, all file/folder names will be obfuscated except the following: 184 185* the file/folder names configured in the 'main' and 'types' fields in the oh-package.json5. 186* the file/folder names configured in the 'srcEntry' field in the module.json5. 187* the file/folder names that are specified by [`-keep-file-name`](#keep-options). 188* non-ECMAScript module reference (ECMAScript module example: `import {foo} from './filename'`) 189* non-path reference, such as json5 will not be obfuscated `import module from 'json5'` 190**Note**: 191**1.** Due to the system loading certain specified files during application runtime, developers need to configure the corresponding white list manually in the [` keep file name `] option to prevent specified files from being confused and causing runtime failures. 192The above situations that require configure white list manually include but are not limited to the following scenarios: 193(1) When the module contains Ability component, you need to configure all paths corresponding to 'srcEntry' in the 'abilities' field in `scr/main/module.json5` to the white list. 194(2) When the module contains multithreading services: Worker, you need to configure all the paths in the field 'buildOption'-'sourceOption'-'workers' in `build-profiles.json5` to the white list. 195 196#### -enable-export-obfuscation 197 198Enable name and property name obfuscation for directly imported or exported classes or objects. If you use this option, the names of direct imports or exports in the module will be obfuscated, except in the following scenarios: 199 200* The names and property names of classes or objects exported in remote HAR (packages with real paths in oh_modules) will not be obfuscated. 201* Names and property names specified by [keep options](#keep-options) will not be obfuscated. 202* Names in the system API list will not be obfuscated. 203 204**Note**: 205 2061. To obfuscate the property names in imported or exported classes, you need to enable both the `-enable-property-obfuscation` and `-enable-export-obfuscation` options. 2072. When compiling HSP, if the `-enable-export-obfuscation` option is used, the externally exposed interfaces need to be kept in the obfuscation configuration file `obfuscation-rules.txt` in the module. 2083. In the scenario where HAP/HSP/HAR depends on HSP, if the `-enable-export-obfuscation` option is used during compilation, the interface imported from HSP needs to be kept in the obfuscation configuration file `obfuscation-rules.txt` in the module. 209 210 ``` 211 // Code example (entry file Index.ets in HSP): 212 export { add, customApiName } from './src/main/ets/utils/Calc' 213 214 // Example of keeping interface name: 215 // obfuscation-rules.txt file configuration in HSP and modules that depend on this HSP: 216 keep-global-name 217 add 218 customApiName 219 ``` 220 221#### -compact 222 223Specifies to remove unnecessary blank spaces and all line feeds. If you use this option, all code will be compressed into 224one line. 225**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. 226 227#### -remove-log 228 229Delete the expressions involving direct calls to console.* statements in the following scenarios: 230 2311. Calls at the toplevel level of a file. 2322. Calls within a block. 2333. Calls within a module. 2344. Calls within a switch statement. 235and the return value of console.* should not be called 236 237#### `-print-namecache` filepath 238 239Specifies to print the name cache that contains the mapping from the old names to new names. 240Note: 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. 241 242#### `-apply-namecache` filepath 243 244Specifies to reuse the given cache file. The old names in the cache will receive the corresponding new names specified in 245the cache. Other names will receive new random short names. This option should be used in incremental obfuscation. 246 247By default, DevEco Studio will keep and update the namecache file in the temporary cache directory and apply the cache for 248incremental compilation. 249Cache directory: build/cache/{...}/release/obfuscation 250 251#### -remove-comments 252 253Remove all comments including single line, multi line and JsDoc comments, in a project except: 254 255* Those names of JsDoc comments above class, function, struct, enum ... in declaration files are in `-keep-comments`. 256**Note**: `-keep-comments` doesn't work for comments in generated source files, which will be deleted. 257 258### Keep options 259 260#### `-keep-property-name` [,identifiers,...] 261 262Specifies property names that you want to keep. For example, 263 264``` 265-keep-property-name 266age 267firstName 268lastName 269``` 270 271**Note**: This option is avaliable when `-enable-property-obfuscation` is enabled. 272 273`-keep-comments` 274To retain JsDoc comments above elements in declaration files, such as preserving the JsDoc comment above the Human class, 275you can make the following configuration: 276 277``` 278-keep-comments 279Human 280``` 281 282**Note**: 283 2841. This option is avaliable when `-remove-comments` is enabled. 2852. If the name of an element is obfuscated, the JsDoc comments 286above that element cannot be kept using `-keep-comments`. For example, when you have exportClass in `-keep-comments`, 287you should make sure that the following class will not be obfuscated, or the JsDoc comments above the class will still be removed: 288 289``` 290/** 291** @class exportClass 292*/ 293export class exportClass {} 294``` 295 296**What property names should be kept?** 297 298For safety, we would suggest keeping all property names that are not accessed through dot syntax. 299 300Example: 301 302``` 303var obj = {x0: 0, x1: 0, x2: 0}; 304for (var i = 0; i <= 2; i++) { 305 console.log(obj['x' + i]); // x0, x1, x2 should be kept 306} 307 308Object.defineProperty(obj, 'y', {}); // y should be kept 309console.log(obj.y); 310 311obj.s = 0; 312let key = 's'; 313console.log(obj[key]); // s should be kept 314 315obj.u = 0; 316console.log(obj.u); // u can be safely obfuscated 317 318obj.t = 0; 319console.log(obj['t']); // t and 't' can be safely obfuscated when `-enable-string-property-obfuscation`, but we suggest keeping t 320 321obj['v'] = 0; 322console.log(obj['v']); // 'v' can be safely obfuscated when `-enable-string-property-obfuscation`, but we suggest keeping v 323``` 324 325In 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. 326 327#### `-keep-global-name` [,identifiers,...] 328 329Specifies names that you want to keep in the global scope. For example, 330 331``` 332-keep-global-name 333Person 334printPersonName 335``` 336 337**What global names should be kept?** 338 339It is known that in javascript the variables in the global scope are properties of `globalThis`. So if in your code 340you access a global variable as a property, then the global name should be kept. 341 342Example: 343 344``` 345var a = 0; 346console.log(globalThis.a); // a should be kept 347 348function foo(){} 349globalThis.foo(); // foo should be kept 350 351var c = 0; 352console.log(c); // c can be safely obfuscated 353 354function bar(){} 355bar(); // bar can be safely obfuscated 356 357class MyClass {} 358let d = new MyClass(); // MyClass can be safely obfuscated 359``` 360 361#### `-keep-file-name` [,identifiers,...] 362 363Specify the name of files/folders to keep (no need to write the file suffix). for example, 364 365``` 366-keep-file-name 367index 368entry 369``` 370 371**What file names should be kept?** 372 373``` 374const module1 = require('./file1') // ARKTs doesn't support CommonJS, this path reference should be kept. 375const moduleName = './file2' 376const module2 = import(moduleName) // dynamic reference cannot identify whether moduleName is a path and should be retained. 377``` 378 379#### `-keep-dts` filepath 380 381Specifies to keep names in the given `.d.ts` file. Here filepath can be also a directory. If so, then the names in all 382`d.ts` files under the given directory will be kept. 383If your are building HAR with this option, then the kept names will be merged into the resulting `obfuscation.txt`. 384 385#### `-keep` path 386 387Names(such as variable names, class names, property names, etc.) in the specified path are not obfuscated. This path can be a file or a folder. If it is a folder, the files in the folder and the files in subfolders will not be obfuscated. 388The path only supports relative paths, `./` and `../` are relative to the directory where the obfuscation configuration file is located. 389 390``` 391-keep 392./src/main/ets/fileName.ts // The names in fileName.ts are not obfusated. 393../folder // The names of files and subfolders in the folder directory are not obfusated. 394../oh_modules/json5 // The names of all files in the referenced library json5 are not obfusated. 395``` 396 397Note: This option does not affect the function of file name obfuscation `-enable-filename-obfuscation` 398 399### Keep options support wildcards 400 401#### Wildcards for name categories 402 403The following options support configuring wildcards for name categories:<br> 404`-keep-property-name`<br> 405`-keep-global-name`<br> 406`-keep-file-name`<br> 407`-keep-comments`<br> 408 409The usage of name categories wildcards is as follows: 410 411| Wildcard | Meaning | Example | 412| -------- | ------------------------------------ | -------------------------------------------------- | 413| ? | Matches any single character | "AB?" can match "ABC", etc., but cannot match "AB" | 414| \* | Matches any number of any characters | "*AB*" can match "AB", "aABb", "cAB", "ABc", etc. | 415 416**Examples**: 417 418Retains all property names starting with 'a': 419 420``` 421-keep-property-name 422a* 423``` 424 425Retains all single-character property names: 426 427``` 428-keep-property-name 429? 430``` 431 432Retains all property names: 433 434``` 435-keep-property-name 436* 437``` 438 439#### Wildcards for path categories 440 441The following options support configuring wildcards for path categories: 442 443`-keep` 444 445The usage of path categories wildcards is as follows: 446 447| Wildcard | Meaning | Example | 448| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | 449| ? | Matches any single character except path separator '/' | "../a?" can match "../ab", etc., but cannot match "../a/" | 450| \* | Matches any number of any characters except path separator '/' | "../a*/c" can match "../ab/c", but cannot match "../ab/d/s/c" | 451| \*\* | Matches any number of any characters | "../a**/c" can match "../ab/c", and also "../ab/d/s/c" | 452| ! | Represents negation and can only be written at the beginning of a path to exclude certain cases that already exist in the user-configured whitelist | "!../a/b/c.ets" means except "../a/b/c.ets" | 453 454**Examples**: 455 456Indicates that the c.ets files in all folders in ../a/b/ (excluding subfolders) will not be obfuscated: 457 458``` 459-keep 460../a/b/*/c.ets 461``` 462 463Indicates that the c.ets files in all folders in ../a/b/ (including subfolders) will not be obfuscated: 464 465``` 466-keep 467../a/b/**/c.ets 468``` 469 470Indicates that except for the c.ets file, all other files in ../a/b/ will not be obfuscated: 471 472``` 473-keep 474../a/b/ 475!../a/b/c.ets 476``` 477 478Meaningless: 479 480``` 481-keep 482!../a/b/c.ets 483``` 484 485Indicates that all files will not be obfuscated: 486 487``` 488-keep 489* 490``` 491 492**Note**: 493 494(1)The above options do not support configuring wildcards '*', '?', '!' for other meanings. 495 496For example: 497 498``` 499class A { 500 '*'= 1 501} 502-keep-property-name 503* 504``` 505 506It becomes ineffective when you only want to retain the '\*' property. 507 508Here, \* indicates matching any number of any characters, resulting in all property names not being obfuscated, rather than only '\*' not being obfuscated. 509 510(2) The -keep option only allows the use of '/' as the path separator and does not support '\\' or '\\\\'. 511 512### Comments 513 514You can write comments in obfuscation rule file by using `#`. The line begins with `#` is treated as comment. 515For example, 516 517``` 518# white list for MainAbility.ets 519-keep-global-name 520MyComponent 521GlobalFunction 522 523-keep-property-name # white list for dynamic property names 524firstName 525lastName 526age 527``` 528 529If your are building HAR, comments will not be merged into the resulting `obfuscation.txt`. 530 531### How Arkguard merges rules 532 533Typically there may be serveral rule files in your project. These rule files come from: 534 535* `ruleOptions.files` in main project (Here by main project we mean the project you are building) 536* `consumerFiles` in local dependent libraries 537* `obfuscate.txt` in remote dependent HARs 538When building your main project, all these rules will be merged by the following strategy (in pseudo code): 539 540``` 541let `listRules` be the list of all rule files that are mentioned above. 542let finalRule = { 543 disableObfuscation: false, 544 enablePropertyObfuscation: false, 545 enableToplevelObfuscation: false, 546 compact: false, 547 removeLog: false, 548 keepPropertyName: [], 549 keepGlobalName: [], 550 keepDts: [], 551 printNamecache: string, 552 applyNamecache: string 553} 554for each file in `listRules`: 555 for each option in file: 556 switch(option) { 557 case -disable-obfuscation: 558 finalRule.disableObfuscation = true; 559 continue; 560 case -enable-property-obfuscation: 561 finalRule.enablePropertyObfuscation = true; 562 continue; 563 case -enable-toplevel-obfuscation: 564 finalRule.enableToplevelObfuscation = true; 565 continue; 566 case -compact: 567 finalRule.compact = true; 568 continue; 569 case -remove-log: 570 finalRule.removeLog = true; 571 continue; 572 case -print-namecache: 573 finalRule.printNamecache = #{specified path}; 574 continue; 575 case -apply-namecache: 576 finalRule.applyNamecache = #{specified path}; 577 continue; 578 case -keep-property-name: 579 finalRule.keepPropertyName.push(#{specified names}); 580 continue; 581 case -keep-global-name: 582 finalRule.keepGlobalName.push(#{specified names}); 583 continue; 584 case -keep-dts: 585 finalRule.keepDts.push(#{specified file path}); 586 continue; 587 } 588 end-for 589end-for 590``` 591 592The final obfuscation rules are in the object `finalRule`. 593 594If you are building HAR, the resulting `obfuscate.txt` are obtained by merging the rules from `consumerFiles` in main 595project and local dependent libraries, and `obfuscate.txt` in remote dependent HARs. The merging strategy is the same 596except: 597 598* The `-keep-dts` option will be converted to `-keep-global-name` and `-keep-property-name` options in the resulting 599`obfuscate.txt`. 600* The options `-print-namecache` and `apply-namecache` will be omitted and will not appear in the resulting 601`obfuscate.txt`. 602