[{"data":1,"prerenderedAt":1086},["ShallowReactive",2],{"navigation_docs":3,"-android-hidden-hardening-key-external":173,"-android-hidden-hardening-key-external-surround":1081},[4,22,29,36,107,138,145,161],{"title":5,"icon":6,"path":7,"stem":8,"children":9},"博客","i-lucide-pen-line","\u002Fblog","0.blog",[10,12,17],{"title":5,"path":7,"stem":11,"icon":6},"0.blog\u002Findex",{"title":13,"path":14,"stem":15,"icon":16},"创建基于 UIKit 的原生 iOS 项目","\u002Fblog\u002Fcreate-uikit-ios-project","0.blog\u002F01.create-uikit-ios-project","i-lucide-app-window",{"title":18,"path":19,"stem":20,"icon":21},"Lockify：把账号和密码留在自己的手机里","\u002Fblog\u002Flockify","0.blog\u002F02.lockify","i-lucide-lock",{"title":23,"path":24,"stem":25,"children":26,"icon":28},"年度总结","\u002Fannual-review","1.annual-review\u002Findex",[27],{"title":23,"path":24,"stem":25,"icon":28},"i-lucide-git-commit",{"title":30,"path":31,"stem":32,"children":33,"icon":35},"故事","\u002Fstories","2.stories\u002Findex",[34],{"title":30,"path":31,"stem":32,"icon":35},"i-lucide-feather",{"title":37,"icon":38,"path":39,"stem":40,"children":41},"Android","i-simple-icons-android","\u002Fandroid","3.android",[42,44,49],{"title":37,"path":39,"stem":43,"icon":38},"3.android\u002Findex",{"title":45,"path":46,"stem":47,"icon":48},"初探Navigation","\u002Fandroid\u002Fcompose-navigation","3.android\u002F01.compose-navigation","i-lucide-route",{"title":50,"icon":51,"path":52,"stem":53,"children":54},"安卓代码加固","i-lucide-shield","\u002Fandroid\u002Fhidden-hardening","3.android\u002F02.hidden-hardening\u002Findex",[55,58,62,67,72,77,82,87,92,97,102],{"title":56,"path":52,"stem":53,"icon":57},"安卓代码加固：总览","i-lucide-map",{"title":59,"path":60,"stem":61,"icon":21},"安卓代码加固（1）：加密DEX","\u002Fandroid\u002Fhidden-hardening\u002Fencrypt-dex","3.android\u002F02.hidden-hardening\u002F01.encrypt-dex",{"title":63,"path":64,"stem":65,"icon":66},"安卓代码加固（2）：Native解密","\u002Fandroid\u002Fhidden-hardening\u002Fnative-decrypt","3.android\u002F02.hidden-hardening\u002F02.native-decrypt","i-lucide-cpu",{"title":68,"path":69,"stem":70,"icon":71},"安卓代码加固（3）：内存加载","\u002Fandroid\u002Fhidden-hardening\u002Fmemory-load","3.android\u002F02.hidden-hardening\u002F03.memory-load","i-lucide-memory-stick",{"title":73,"path":74,"stem":75,"icon":76},"安卓代码加固（4）：指令分发","\u002Fandroid\u002Fhidden-hardening\u002Fopcode-dispatch","3.android\u002F02.hidden-hardening\u002F04.opcode-dispatch","i-lucide-hash",{"title":78,"path":79,"stem":80,"icon":81},"安卓代码加固（5）：XOR混淆","\u002Fandroid\u002Fhidden-hardening\u002Fxor-obfuscate","3.android\u002F02.hidden-hardening\u002F05.xor-obfuscate","i-lucide-shuffle",{"title":83,"path":84,"stem":85,"icon":86},"安卓代码加固（6）：密钥外置","\u002Fandroid\u002Fhidden-hardening\u002Fkey-external","3.android\u002F02.hidden-hardening\u002F06.key-external","i-lucide-key",{"title":88,"path":89,"stem":90,"icon":91},"安卓代码加固（7）：依赖隔离","\u002Fandroid\u002Fhidden-hardening\u002Fdep-isolate","3.android\u002F02.hidden-hardening\u002F07.dep-isolate","i-lucide-layers",{"title":93,"path":94,"stem":95,"icon":96},"安卓代码加固（8）：构建校验","\u002Fandroid\u002Fhidden-hardening\u002Fbuild-verify","3.android\u002F02.hidden-hardening\u002F08.build-verify","i-lucide-shield-check",{"title":98,"path":99,"stem":100,"icon":101},"安卓代码加固（9）：防录屏","\u002Fandroid\u002Fhidden-hardening\u002Fflag-secure","3.android\u002F02.hidden-hardening\u002F09.flag-secure","i-lucide-eye-off",{"title":103,"path":104,"stem":105,"icon":106},"安卓代码加固（10）：ABI门禁","\u002Fandroid\u002Fhidden-hardening\u002Fabi-gate","3.android\u002F02.hidden-hardening\u002F10.abi-gate","i-lucide-git-compare",{"title":108,"icon":109,"path":110,"stem":111,"children":112},"iOS","i-simple-icons-apple","\u002Fios","4.ios",[113,115,120,125,129,133],{"title":108,"path":110,"stem":114,"icon":109},"4.ios\u002Findex",{"title":116,"path":117,"stem":118,"icon":119},"iOS面试题1","\u002Fios\u002Fios-interview1","4.ios\u002F01.ios-interview1","i-lucide-sparkles",{"title":121,"path":122,"stem":123,"icon":124},"设置启动图","\u002Fios\u002Fset-launch-screen","4.ios\u002F02.set-launch-screen","i-lucide-image",{"title":126,"path":127,"stem":128,"icon":48},"路由管理","\u002Fios\u002Frouting","4.ios\u002F03.routing",{"title":130,"path":131,"stem":132,"icon":91},"状态管理","\u002Fios\u002Fstate-management","4.ios\u002F04.state-management",{"title":134,"path":135,"stem":136,"icon":137},"事件传递","\u002Fios\u002Fevent-delivery","4.ios\u002F05.event-delivery","i-lucide-pointer",{"title":139,"path":140,"stem":141,"children":142,"icon":144},"Flutter","\u002Fflutter","5.flutter\u002Findex",[143],{"title":139,"path":140,"stem":141,"icon":144},"i-simple-icons-flutter",{"title":146,"icon":147,"path":148,"stem":149,"children":150,"page":160},"面试","i-lucide-graduation-cap","\u002Finterview","6.interview",[151,156],{"title":152,"path":153,"stem":154,"icon":155},"Flutter面试题1","\u002Finterview\u002Fflutter-interview1","6.interview\u002F01.flutter-interview1","i-lucide-boxes",{"title":157,"path":158,"stem":159,"icon":66},"Flutter面试题2","\u002Finterview\u002Fflutter-interview2","6.interview\u002F02.flutter-interview2",false,{"title":162,"icon":163,"path":164,"stem":165,"children":166},"算法学习","i-lucide-binary","\u002Falgorithm","7.algorithm",[167,169],{"title":162,"path":164,"stem":168,"icon":163},"7.algorithm\u002Findex",{"title":170,"path":171,"stem":172},"算法基础1：复杂度分析","\u002Falgorithm\u002Ftime-space-complexity","7.algorithm\u002F01.time-space-complexity",{"id":174,"title":83,"body":175,"description":1064,"extension":1065,"links":1066,"meta":1069,"navigation":1076,"path":84,"seo":1077,"stem":85,"__hash__":1080},"docs\u002F3.android\u002F02.hidden-hardening\u002F06.key-external.md",{"type":176,"value":177,"toc":1053},"minimark",[178,192,200,204,215,384,391,394,400,440,779,788,792,802,854,890,912,924,927,1019,1026,1029,1049],[179,180,181,182,186,187,191],"p",{},"用于解开 payload 的 32 字节密钥 ",[183,184,185],"strong",{},"不在"," ",[188,189,190],"code",{},"hidden-sdk"," 源码、AAR 和 so 里。谁打包，谁持有密钥；谁接入，谁在运行时传入。拿到 AAR 并不等于能够加载 dex。",[193,194,195,196,199],"caution",{},"Demo 为了能直接安装，把同一串密钥写进 ",[188,197,198],{},"BuildConfig.HIDDEN_PAYLOAD_KEY","。正式接入不要沿用这一做法，应改成接入方自己的安全存储或下发通道。",[201,202,203],"h2",{"id":203},"密钥格式",[179,205,206,207,210,211,214],{},"必须是 ",[183,208,209],{},"正好 64 个 hex 字符","（",[188,212,213],{},"0-9a-fA-F","），解码为 32 随机字节，作为 AES-256-GCM 密钥。不能把口令的 UTF-8 字节直接当作 key。",[216,217,223],"pre",{"className":218,"code":219,"filename":220,"language":221,"meta":222,"style":222},"language-kotlin shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const val KEY_HEX_LENGTH = 64\n\nfun isUsableKey(hex: String): Boolean {\n    if (hex.length != KEY_HEX_LENGTH) return false\n    return hex.all { ch ->\n        ch in '0'..'9' || ch in 'a'..'f' || ch in 'A'..'F'\n    }\n}\n","hidden-sdk\u002Fsrc\u002Fmain\u002Fjava\u002Fcom\u002Fexample\u002Fminidex\u002Fsdk\u002Finternal\u002FHiddenCrypto.kt","kotlin","",[188,224,225,249,256,282,305,323,372,378],{"__ignoreMap":222},[226,227,230,234,238,242,245],"span",{"class":228,"line":229},"line",1,[226,231,233],{"class":232},"spNyl","const",[226,235,237],{"class":236},"sMK4o"," val",[226,239,241],{"class":240},"sTEyZ"," KEY_HEX_LENGTH ",[226,243,244],{"class":236},"=",[226,246,248],{"class":247},"sbssI"," 64\n",[226,250,252],{"class":228,"line":251},2,[226,253,255],{"emptyLinePlaceholder":254},true,"\n",[226,257,259,262,266,269,273,276,279],{"class":228,"line":258},3,[226,260,261],{"class":236},"fun",[226,263,265],{"class":264},"s2Zo4"," isUsableKey",[226,267,268],{"class":240},"(hex: ",[226,270,272],{"class":271},"sBMFI","String",[226,274,275],{"class":240},"): ",[226,277,278],{"class":271},"Boolean",[226,280,281],{"class":240}," {\n",[226,283,285,289,292,295,298,301],{"class":228,"line":284},4,[226,286,288],{"class":287},"s7zQu","    if",[226,290,291],{"class":240}," (hex.length ",[226,293,294],{"class":236},"!=",[226,296,297],{"class":240}," KEY_HEX_LENGTH) ",[226,299,300],{"class":287},"return",[226,302,304],{"class":303},"sfNiH"," false\n",[226,306,308,311,314,317,320],{"class":228,"line":307},5,[226,309,310],{"class":287},"    return",[226,312,313],{"class":240}," hex.",[226,315,316],{"class":264},"all",[226,318,319],{"class":240}," { ch ",[226,321,322],{"class":232},"->\n",[226,324,326,329,332,336,339,342,345,348,350,353,355,358,360,362,364,367,369],{"class":228,"line":325},6,[226,327,328],{"class":240},"        ch ",[226,330,331],{"class":236},"in",[226,333,335],{"class":334},"sfazB"," '0'",[226,337,338],{"class":236},"..",[226,340,341],{"class":334},"'9'",[226,343,344],{"class":236}," ||",[226,346,347],{"class":240}," ch ",[226,349,331],{"class":236},[226,351,352],{"class":334}," 'a'",[226,354,338],{"class":236},[226,356,357],{"class":334},"'f'",[226,359,344],{"class":236},[226,361,347],{"class":240},[226,363,331],{"class":236},[226,365,366],{"class":334}," 'A'",[226,368,338],{"class":236},[226,370,371],{"class":334},"'F'\n",[226,373,375],{"class":228,"line":374},7,[226,376,377],{"class":240},"    }\n",[226,379,381],{"class":228,"line":380},8,[226,382,383],{"class":240},"}\n",[179,385,386,387,390],{},"Java 只检查格式。把 hex 转为 32 字节发生在 so 的 ",[188,388,389],{},"parse_key_hex","。nonce 写在密文头里，不随密钥一起分发。",[201,392,393],{"id":393},"解析打包密钥",[179,395,396,399],{},[188,397,398],{},"tools\u002Fpayload_key.py"," 的优先级：",[401,402,403,407,413,416,426,429],"steps",{},[404,405,406],"h3",{"id":406},"环境变量",[179,408,409,412],{},[188,410,411],{},"HIDDEN_PAYLOAD_KEY"," 有值就用它。CI \u002F release 必须走这条路径。",[404,414,415],{"id":415},"本地文件",[179,417,418,421,422,425],{},[188,419,420],{},"tools\u002F.payload_key"," 存在则读取。该文件已在 ",[188,423,424],{},".gitignore","。",[404,427,428],{"id":428},"允许时生成",[179,430,431,432,435,436,439],{},"仅 debug 且带 ",[188,433,434],{},"--allow-generate"," 时，用 ",[188,437,438],{},"secrets.token_hex(32)"," 写文件。release 任务不带这个开关。",[216,441,445],{"className":442,"code":443,"filename":398,"language":444,"meta":222,"style":222},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","ENV_NAME = \"HIDDEN_PAYLOAD_KEY\"\nKEY_FILE = Path(__file__).resolve().parent \u002F \".payload_key\"\n\ndef resolve(*, require_env: bool, allow_generate: bool) -> str:\n    env = os.environ.get(ENV_NAME, \"\").strip()\n    if env:\n        return validate(env)\n    if require_env:\n        raise SystemExit(f\"Release \u002F CI 打包必须设置环境变量 {ENV_NAME}\")\n    if KEY_FILE.exists():\n        return validate(KEY_FILE.read_text())\n    if not allow_generate:\n        raise SystemExit(\"没有密钥，也没有本地文件\")\n    key = secrets.token_hex(32)\n    KEY_FILE.write_text(key + \"\\n\")\n    return key\n","python",[188,446,447,462,501,505,551,590,599,615,624,654,670,690,702,720,743,771],{"__ignoreMap":222},[226,448,449,452,454,457,459],{"class":228,"line":229},[226,450,451],{"class":240},"ENV_NAME ",[226,453,244],{"class":236},[226,455,456],{"class":236}," \"",[226,458,411],{"class":334},[226,460,461],{"class":236},"\"\n",[226,463,464,467,469,472,475,478,481,484,487,491,494,496,499],{"class":228,"line":251},[226,465,466],{"class":240},"KEY_FILE ",[226,468,244],{"class":236},[226,470,471],{"class":264}," Path",[226,473,474],{"class":236},"(",[226,476,477],{"class":240},"__file__",[226,479,480],{"class":236},").",[226,482,483],{"class":264},"resolve",[226,485,486],{"class":236},"().",[226,488,490],{"class":489},"swJcz","parent",[226,492,493],{"class":236}," \u002F",[226,495,456],{"class":236},[226,497,498],{"class":334},".payload_key",[226,500,461],{"class":236},[226,502,503],{"class":228,"line":258},[226,504,255],{"emptyLinePlaceholder":254},[226,506,507,510,513,516,519,523,526,529,532,535,537,539,542,545,548],{"class":228,"line":284},[226,508,509],{"class":232},"def",[226,511,512],{"class":264}," resolve",[226,514,515],{"class":236},"(*",[226,517,518],{"class":240},", ",[226,520,522],{"class":521},"sHdIc","require_env",[226,524,525],{"class":236},":",[226,527,528],{"class":271}," bool",[226,530,531],{"class":236},",",[226,533,534],{"class":521}," allow_generate",[226,536,525],{"class":236},[226,538,528],{"class":271},[226,540,541],{"class":236},")",[226,543,544],{"class":236}," ->",[226,546,547],{"class":271}," str",[226,549,550],{"class":236},":\n",[226,552,553,556,558,561,564,567,569,572,574,577,579,582,584,587],{"class":228,"line":307},[226,554,555],{"class":240},"    env ",[226,557,244],{"class":236},[226,559,560],{"class":240}," os",[226,562,563],{"class":236},".",[226,565,566],{"class":489},"environ",[226,568,563],{"class":236},[226,570,571],{"class":264},"get",[226,573,474],{"class":236},[226,575,576],{"class":264},"ENV_NAME",[226,578,531],{"class":236},[226,580,581],{"class":236}," \"\"",[226,583,480],{"class":236},[226,585,586],{"class":264},"strip",[226,588,589],{"class":236},"()\n",[226,591,592,594,597],{"class":228,"line":325},[226,593,288],{"class":287},[226,595,596],{"class":240}," env",[226,598,550],{"class":236},[226,600,601,604,607,609,612],{"class":228,"line":374},[226,602,603],{"class":287},"        return",[226,605,606],{"class":264}," validate",[226,608,474],{"class":236},[226,610,611],{"class":264},"env",[226,613,614],{"class":236},")\n",[226,616,617,619,622],{"class":228,"line":380},[226,618,288],{"class":287},[226,620,621],{"class":240}," require_env",[226,623,550],{"class":236},[226,625,627,630,633,635,638,641,644,646,649,652],{"class":228,"line":626},9,[226,628,629],{"class":287},"        raise",[226,631,632],{"class":271}," SystemExit",[226,634,474],{"class":236},[226,636,637],{"class":232},"f",[226,639,640],{"class":334},"\"Release \u002F CI 打包必须设置环境变量 ",[226,642,643],{"class":247},"{",[226,645,576],{"class":264},[226,647,648],{"class":247},"}",[226,650,651],{"class":334},"\"",[226,653,614],{"class":236},[226,655,657,659,662,664,667],{"class":228,"line":656},10,[226,658,288],{"class":287},[226,660,661],{"class":240}," KEY_FILE",[226,663,563],{"class":236},[226,665,666],{"class":264},"exists",[226,668,669],{"class":236},"():\n",[226,671,673,675,677,679,682,684,687],{"class":228,"line":672},11,[226,674,603],{"class":287},[226,676,606],{"class":264},[226,678,474],{"class":236},[226,680,681],{"class":264},"KEY_FILE",[226,683,563],{"class":236},[226,685,686],{"class":264},"read_text",[226,688,689],{"class":236},"())\n",[226,691,693,695,698,700],{"class":228,"line":692},12,[226,694,288],{"class":287},[226,696,697],{"class":236}," not",[226,699,534],{"class":240},[226,701,550],{"class":236},[226,703,705,707,709,711,713,716,718],{"class":228,"line":704},13,[226,706,629],{"class":287},[226,708,632],{"class":271},[226,710,474],{"class":236},[226,712,651],{"class":236},[226,714,715],{"class":334},"没有密钥，也没有本地文件",[226,717,651],{"class":236},[226,719,614],{"class":236},[226,721,723,726,728,731,733,736,738,741],{"class":228,"line":722},14,[226,724,725],{"class":240},"    key ",[226,727,244],{"class":236},[226,729,730],{"class":240}," secrets",[226,732,563],{"class":236},[226,734,735],{"class":264},"token_hex",[226,737,474],{"class":236},[226,739,740],{"class":247},"32",[226,742,614],{"class":236},[226,744,746,749,751,754,756,759,762,764,767,769],{"class":228,"line":745},15,[226,747,748],{"class":240},"    KEY_FILE",[226,750,563],{"class":236},[226,752,753],{"class":264},"write_text",[226,755,474],{"class":236},[226,757,758],{"class":264},"key ",[226,760,761],{"class":236},"+",[226,763,456],{"class":236},[226,765,766],{"class":240},"\\n",[226,768,651],{"class":236},[226,770,614],{"class":236},[226,772,774,776],{"class":228,"line":773},16,[226,775,310],{"class":287},[226,777,778],{"class":240}," key\n",[179,780,781,784,785,787],{},[188,782,783],{},"encryptHiddenPayloadRelease"," 不传 ",[188,786,434],{},"。没有环境变量就无法完成编译。",[201,789,791],{"id":790},"demo-如何注入密钥","Demo 如何注入密钥",[179,793,794,797,798,801],{},[188,795,796],{},":app"," 在配置期跑同一套脚本，把结果写进 ",[188,799,800],{},"BuildConfig","：",[216,803,806],{"className":218,"code":804,"filename":805,"language":221,"meta":222,"style":222},"buildConfigField(\"String\", \"HIDDEN_PAYLOAD_KEY\", \"\\\"${resolveHiddenPayloadKey(allowGenerate = true)}\\\"\")\n","app\u002Fbuild.gradle.kts",[188,807,808],{"__ignoreMap":222},[226,809,810,813,815,818,820,823,825,827,830,833,836,839,841,844,846,848,850,852],{"class":228,"line":229},[226,811,812],{"class":264},"buildConfigField",[226,814,474],{"class":240},[226,816,817],{"class":334},"\"String\"",[226,819,518],{"class":240},[226,821,822],{"class":334},"\"HIDDEN_PAYLOAD_KEY\"",[226,824,518],{"class":240},[226,826,651],{"class":334},[226,828,829],{"class":240},"\\\"",[226,831,832],{"class":236},"${",[226,834,835],{"class":264},"resolveHiddenPayloadKey",[226,837,838],{"class":240},"(allowGenerate ",[226,840,244],{"class":236},[226,842,843],{"class":303}," true",[226,845,541],{"class":240},[226,847,648],{"class":236},[226,849,829],{"class":240},[226,851,651],{"class":334},[226,853,614],{"class":240},[216,855,858],{"className":218,"code":856,"filename":857,"language":221,"meta":222,"style":222},"object DemoPayloadKeys {\n    val PAYLOAD_KEY: String = BuildConfig.HIDDEN_PAYLOAD_KEY\n}\n","app\u002Fsrc\u002Fmain\u002Fjava\u002Fcom\u002Fexample\u002Fminidex\u002FDemoPayloadKeys.kt",[188,859,860,870,886],{"__ignoreMap":222},[226,861,862,865,868],{"class":228,"line":229},[226,863,864],{"class":236},"object",[226,866,867],{"class":271}," DemoPayloadKeys",[226,869,281],{"class":240},[226,871,872,875,878,880,883],{"class":228,"line":251},[226,873,874],{"class":236},"    val",[226,876,877],{"class":240}," PAYLOAD_KEY: ",[226,879,272],{"class":271},[226,881,882],{"class":236}," =",[226,884,885],{"class":240}," BuildConfig.HIDDEN_PAYLOAD_KEY\n",[226,887,888],{"class":228,"line":258},[226,889,383],{"class":240},[216,891,894],{"className":218,"code":892,"filename":893,"language":221,"meta":222,"style":222},"HiddenSdk.init(this, DemoPayloadKeys.PAYLOAD_KEY)\n","app\u002Fsrc\u002Fmain\u002Fjava\u002Fcom\u002Fexample\u002Fminidex\u002FDemoApplication.kt",[188,895,896],{"__ignoreMap":222},[226,897,898,901,904,906,909],{"class":228,"line":229},[226,899,900],{"class":240},"HiddenSdk.",[226,902,903],{"class":264},"init",[226,905,474],{"class":240},[226,907,908],{"class":236},"this",[226,910,911],{"class":240},", DemoPayloadKeys.PAYLOAD_KEY)\n",[179,913,914,917,918,425,920,923],{},[188,915,916],{},"Application.onCreate"," 必须尽早调用 ",[188,919,903],{},[188,921,922],{},"ConnectionService"," 可能在首页尚未打开时就被系统拉起。密钥为空时不读取 assets，也不创建 ClassLoader。",[201,925,926],{"id":926},"对照失败码",[928,929,930,945],"table",{},[931,932,933],"thead",{},[934,935,936,939,942],"tr",{},[937,938,188],"th",{},[937,940,941],{},"含义",[937,943,944],{},"会加载 dex 吗",[946,947,948,969,981,993,1006],"tbody",{},[934,949,950,956,966],{},[951,952,953],"td",{},[188,954,955],{},"EMPTY_KEY",[951,957,958,961,962,965],{},[188,959,960],{},"null"," \u002F ",[188,963,964],{},"\"\""," \u002F 空白",[951,967,968],{},"否",[934,970,971,976,979],{},[951,972,973],{},[188,974,975],{},"INVALID_KEY",[951,977,978],{},"不是 64 hex，或解不开 \u002F 不是 dex",[951,980,968],{},[934,982,983,988,991],{},[951,984,985],{},[188,986,987],{},"LOAD_FAILED",[951,989,990],{},"payload 缺失、native 失败、ABI 不匹配",[951,992,968],{},[934,994,995,1000,1003],{},[951,996,997],{},[188,998,999],{},"SUCCESS",[951,1001,1002],{},"本次解密并加载",[951,1004,1005],{},"是",[934,1007,1008,1013,1016],{},[951,1009,1010],{},[188,1011,1012],{},"ALREADY_INITIALIZED",[951,1014,1015],{},"进程里已经成功过",[951,1017,1018],{},"不再重解",[1020,1021,1022,1023,1025],"tip",{},"已经成功后再 ",[188,1024,903],{},"，不会用新密钥重新解密。更换密钥只能重启进程。",[201,1027,1028],{"id":1028},"下一步",[1030,1031,1032,1043],"ul",{},[1033,1034,1035,1039,1040],"li",{},[1036,1037,1038],"a",{"href":60},"加密DEX","：打包时密钥如何进入 ",[188,1041,1042],{},"PayloadEncryptor",[1033,1044,1045,1048],{},[1036,1046,1047],{"href":94},"构建校验","：AAR 自检不会、也不该读到密钥",[1050,1051,1052],"style",{},"html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":222,"searchDepth":251,"depth":251,"links":1054},[1055,1056,1061,1062,1063],{"id":203,"depth":251,"text":203},{"id":393,"depth":251,"text":393,"children":1057},[1058,1059,1060],{"id":406,"depth":258,"text":406},{"id":415,"depth":258,"text":415},{"id":428,"depth":258,"text":428},{"id":790,"depth":251,"text":791},{"id":926,"depth":251,"text":926},{"id":1028,"depth":251,"text":1028},"SDK \u002F AAR 不带 AES 密钥。CI 用环境变量，本地 debug 用 gitignore 文件。","md",[1067,1068],{"label":59,"icon":21,"to":60},{"label":63,"icon":66,"to":64},{"date":1070,"categories":1071,"tags":1073},"2026-09-21",[1072],"android",[37,1074,1075],"密钥","CI",{"icon":86},{"title":1078,"description":1079},"安卓代码加固（6）：Hidden DEX 密钥外置与 64 hex 约定","hidden-dex-minidemo 的 AES-256 密钥不打进 AAR。打包读 HIDDEN_PAYLOAD_KEY 或 tools\u002F.payload_key，运行时由宿主传入同一串 64 hex。","mNa7mBtK0kT6i6M2rQc01RbZEUoPYbYtpKpzGIBk22Q",[1082,1084],{"title":78,"path":79,"stem":80,"description":1083,"icon":81,"children":-1},"so 里的资源路径、实现类名、方法名按 0x5A 异或存放，用完立即清零。",{"title":88,"path":89,"stem":90,"description":1085,"icon":91,"children":-1},"宿主只 implementation hidden-sdk。landing-page 对 SDK 必须 compileOnly，明文 class 不准进入 APK。",1790767046593]