├── README.md ├── main.js ├── package.json └── panel ├── apply_jsb.js ├── apply_web.js ├── encripter.js ├── index.css ├── index.html ├── index.js ├── md5_util.js ├── template_web_index.html └── web_downloader.js /README.md: -------------------------------------------------------------------------------- 1 | # hyz-encript 2 | cocoscreator加密混淆,基于2.4.5编写,理论上适用于引擎2.4.0-2.4.6,最重要是开源。 3 | ![截图](https://user-images.githubusercontent.com/11954247/141231612-5fe82cd1-a27a-4f16-ae22-d299c13b17a0.png) 4 | 5 | 6 | 功能: 7 | - **web端**支持加密图片、text、json 8 | - **native端**支持加密除音频外所有资源 9 | - 支持文件名混淆 10 | 11 | **加密思路:** 12 | 加密是最简单的异或加密,修改构建后的源码进行解密。native端是修改c++端CCFileUtil的文件读取函数,web端是修改cocos2d-jsb.js的download系列方法。 13 | 14 | **文件名修改思路:** 15 | 提取文件名,重命名为文件名的md5码;然后下载资源前,先修改transformUrl函数, 16 | 将本地文件名同样算一遍md5,进行重定向; 17 | 18 | **使用方式:** 19 | 必须先构建,目前支持jsb-link、web-mobile、web-desktop,然后再打开插件,选择对应的而构建方式,填上加密签名、秘钥,点击加密按钮即可。 20 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | load () { 5 | // execute when package loaded 6 | }, 7 | 8 | unload () { 9 | // execute when package unloaded 10 | }, 11 | 12 | // register your ipc messages here 13 | messages: { 14 | 'showPanel' () { 15 | Editor.Panel.open('hyz-encript'); 16 | Editor.log('欢迎使用hyz-encript'); 17 | }, 18 | }, 19 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hyz-encript", 3 | "version": "0.0.1", 4 | "description": "The package template for getting started.", 5 | "author": "Cocos Creator", 6 | "main": "main.js", 7 | "main-menu": { 8 | "i18n:MAIN_MENU.package.title/hyz-encript": { 9 | "message": "hyz-encript:showPanel" 10 | } 11 | }, 12 | "panel": { 13 | "main": "panel/index.js", 14 | "type": "dockable", 15 | "title": "hyz-encript", 16 | "width": 600, 17 | "height": 400, 18 | "min-width": 600, 19 | "min-height": 400, 20 | "max-width": 600, 21 | "max-height": 400 22 | } 23 | } -------------------------------------------------------------------------------- /panel/apply_jsb.js: -------------------------------------------------------------------------------- 1 | let Fs = require('fs'); 2 | let Path = require('path'); 3 | 4 | let cpp_str; 5 | let h_str; 6 | let engine_str; 7 | { 8 | cpp_str = `bool FileUtils::init() 9 | { 10 | _searchPathArray.push_back(_defaultResRootPath); 11 | _searchResolutionsOrderArray.push_back(""); 12 | setDecriptKeyAndSign("tempEncriptSign","tempEncriptKey"); 13 | return true; 14 | } 15 | 16 | void FileUtils::setDecriptKeyAndSign(std::string sign, std::string key) 17 | { 18 | this->decriptSign = sign; 19 | this->decriptKey = key; 20 | } 21 | 22 | void FileUtils::purgeCachedEntries() 23 | { 24 | _fullPathCache.clear(); 25 | } 26 | 27 | std::string FileUtils::getStringFromFile(const std::string& filename) 28 | { 29 | std::string s; 30 | getContents(filename, &s); 31 | if (s.length() > decriptSign.size() && s.find(decriptSign.c_str()) == 0) { 32 | s.erase(0, decriptSign.size()); 33 | int kindex = 0; 34 | for (int i = 0; i < s.length(); i++) { 35 | if (kindex >= decriptKey.size()) kindex = 0; 36 | s[i] ^= decriptKey[kindex]; 37 | kindex++; 38 | } 39 | } 40 | return s; 41 | } 42 | 43 | Data FileUtils::getDataFromFile(const std::string& filename) 44 | { 45 | Data d; 46 | getContents(filename, &d); 47 | if (d.getSize() > 4) { 48 | unsigned char* bytes = d.getBytes(); 49 | if (memcmp(bytes, decriptSign.c_str(), decriptSign.size()) == 0) { 50 | ssize_t realSize = d.getSize() - decriptSign.size(); 51 | unsigned char* data = (unsigned char*)calloc(1, realSize); 52 | memcpy(data, bytes + decriptSign.size(), realSize); 53 | int kindex = 0; 54 | for (int i = 0; i < realSize; i++) { 55 | if (kindex >= decriptKey.size()) kindex = 0; 56 | data[i] ^= decriptKey[kindex]; 57 | kindex++; 58 | } 59 | d.fastSet(data, realSize); 60 | } 61 | } 62 | return d; 63 | } 64 | 65 | 66 | FileUtils::Status FileUtils::getContents(const std::string& filename, ResizableBuffer* buffer)` 67 | 68 | h_str = `virtual void valueVectorCompact(ValueVector& valueVector); 69 | 70 | std::string decriptSign = "sign"; 71 | std::string decriptKey = "key"; 72 | 73 | public: 74 | void setDecriptKeyAndSign(std::string sign = "",std::string key = ""); 75 | }; 76 | 77 | // end of support group 78 | /** @} */ 79 | 80 | NS_CC_END 81 | 82 | #endif // __CC_FILEUTILS_H__` 83 | 84 | engine_str = `function _getRealPath(path) { 85 | let excludeChangeNameList = [".mp3",".ogg",".wav",".js",".jsc",] 86 | if(path.indexOf("assets")!=0){ 87 | return path 88 | } 89 | if(!needMixFilename){//tag 90 | return path; 91 | } 92 | for(let ext of excludeChangeNameList){ 93 | if(path.endsWith(ext)){ 94 | return path 95 | } 96 | } 97 | var ext = path.substr(path.lastIndexOf(".")); 98 | var arr = path.split('/'); 99 | let name = arr[arr.length-1]; 100 | let realPath = path; 101 | 102 | if(name[8]=="-"&&name[13]=="-"&&name[18]=="-"&&name[23]=="-"){ 103 | let md5 = hyz.str_to_md5(name+'tag') 104 | let arr2 = [8,13,18,23] 105 | for(let i = arr2.length-1;i>=0;i--){ 106 | let idx = arr2[i]; 107 | md5 = md5.slice(0, idx) + "-" + md5.slice(idx); 108 | } 109 | md5+=ext; 110 | 111 | realPath = path.replace(name,md5); 112 | realPath = realPath.replace("/"+name.slice(0,2)+"/","/"+md5.slice(0,2)+"/"); 113 | realPath = realPath.replace("\\\\"+name.slice(0,2)+"\\\\","\\\\"+md5.slice(0,2)+"\\\\"); 114 | } 115 | 116 | return realPath 117 | }; 118 | 119 | 120 | function transformUrl(url, options) { 121 | var inLocal = false; 122 | var inCache = false; 123 | 124 | if (REGEX.test(url)) { 125 | if (options.reload) { 126 | return { 127 | url: url 128 | }; 129 | } else { 130 | var cache = cacheManager.getCache(url); 131 | 132 | if (cache) { 133 | inCache = true; 134 | url = cache; 135 | } 136 | } 137 | } else { 138 | inLocal = true; 139 | url = _getRealPath(url) 140 | } 141 | 142 | return { 143 | url: url, 144 | inLocal: inLocal, 145 | inCache: inCache 146 | }; 147 | } 148 | 149 | function doNothing(content, options, onComplete) {` 150 | } 151 | 152 | function strToBytes(str){ 153 | let size = str.length; 154 | let result = []; 155 | for(let i=0;i=0){ 218 | return; 219 | } 220 | 221 | let arr_1 = oldStr.split("function transformUrl(url, options) {"); 222 | let arr_2 = oldStr.split("function doNothing(content, options, onComplete) {"); 223 | 224 | let str = engine_str; 225 | str = str.replace("if(!needMixFilename){//tag",`if(!${needMixFilename}){//tag`) 226 | str = str.replace("let md5 = hyz.str_to_md5(name+'tag')",`let md5 = hyz.str_to_md5(name+"${nameMixSign}")`) 227 | let newStr = arr_1[0]+str+arr_2[1]; 228 | Fs.writeFileSync(jsEnjinePath,newStr); 229 | } 230 | 231 | function insertToFileUtils() { 232 | let enginePath = Editor.url("unpack://engine") 233 | let cocosPlatformPath = Path.join(enginePath,"../cocos2d-x/cocos/platform") 234 | Editor.log("cocosPlatformPath",cocosPlatformPath) 235 | 236 | let CCFileUtils_h = Path.join(cocosPlatformPath,"CCFileUtils.h") 237 | let CCFileUtils_cpp = Path.join(cocosPlatformPath,"CCFileUtils.cpp") 238 | 239 | do{ 240 | let hStr = Fs.readFileSync(CCFileUtils_h,'utf8'); 241 | if(hStr.indexOf("setDecriptKeyAndSign")>=0){ 242 | break; 243 | } 244 | let arr_1 = hStr.split("virtual void valueVectorCompact(ValueVector& valueVector);"); 245 | let arr_2 = hStr.split("#endif // __CC_FILEUTILS_H__"); 246 | 247 | let newStr = arr_1[0]+h_str+arr_2[1]; 248 | if(!Fs.existsSync(CCFileUtils_h+".bak")){ 249 | Fs.copyFile(CCFileUtils_h,CCFileUtils_h+".bak",function (err) {}) 250 | } 251 | 252 | /**直接写会写失败,曲折一下 */ 253 | // Fs.writeFileSync(CCFileUtils_h,newStr); 254 | Fs.unlinkSync(CCFileUtils_h) 255 | Fs.writeFileSync(CCFileUtils_h+".temp",newStr); 256 | Fs.copyFile(CCFileUtils_h+".temp",CCFileUtils_h,function (err) {if(err){Editor.log(err)}}) 257 | Fs.unlinkSync(CCFileUtils_h+".temp") 258 | }while(false) 259 | 260 | do{ 261 | let keyLine = `setDecriptKeyAndSign("${encriptSign}","${encriptKey}");` 262 | let cppStr = Fs.readFileSync(CCFileUtils_cpp,'utf8'); 263 | if(cppStr.indexOf(keyLine)>=0){ 264 | break; 265 | } 266 | let arr_1 = cppStr.split("bool FileUtils::init()") 267 | let arr_2 = cppStr.split("FileUtils::Status FileUtils::getContents(const std::string& filename, ResizableBuffer* buffer)") 268 | 269 | cpp_str = cpp_str.replace('setDecriptKeyAndSign("tempEncriptSign","tempEncriptKey");',keyLine) 270 | let newStr = arr_1[0]+cpp_str+arr_2[1]; 271 | if(!Fs.existsSync(CCFileUtils_cpp+".bak")){ 272 | Fs.copyFile(CCFileUtils_cpp,CCFileUtils_cpp+".bak",function (err) {}) 273 | } 274 | 275 | /**直接写会写失败,曲折一下 */ 276 | // Fs.writeFileSync(CCFileUtils_cpp,newStr); 277 | Fs.unlinkSync(CCFileUtils_cpp) 278 | Fs.writeFileSync(CCFileUtils_cpp+".temp",newStr); 279 | Fs.copyFile(CCFileUtils_cpp+".temp",CCFileUtils_cpp,function (err) {if(err){Editor.log(err)}}) 280 | Fs.unlinkSync(CCFileUtils_cpp+".temp") 281 | }while(false) 282 | } 283 | 284 | 285 | module.exports = function applyJsb({_buildFloderPath,_encriptSign,_encriptKey,_needMixFilename,_nameMixSign}) { 286 | buildFloderPath = _buildFloderPath 287 | encriptSign = _encriptSign 288 | encriptKey = _encriptKey 289 | needMixFilename = _needMixFilename 290 | nameMixSign = _nameMixSign 291 | Editor.log("=jsbbb========nameMixSign",nameMixSign) 292 | copyHelper(); 293 | insertToJsEngineJs(); 294 | insertToFileUtils(); 295 | } -------------------------------------------------------------------------------- /panel/apply_web.js: -------------------------------------------------------------------------------- 1 | let Fs = require('fs'); 2 | let Path = require('path'); 3 | 4 | let buildFloderPath = null; 5 | let encriptSign = ""; 6 | let encriptKey = ""; 7 | let needMixFilename = ""; 8 | let nameMixSign = ""; 9 | 10 | function copyHelper() { 11 | let fromPath = Editor.url("packages://hyz-encript/panel/md5_util.js","utf-8"); 12 | let toPath = Path.join(buildFloderPath,"assets","md5_util.js"); 13 | Fs.copyFile(fromPath,toPath,function (err) { 14 | if(err){ 15 | Editor.error("复制md5_util.js出错") 16 | } 17 | }); 18 | 19 | fromPath = Editor.url("packages://hyz-encript/panel/web_downloader.js","utf-8"); 20 | toPath = Path.join(buildFloderPath,"assets","web_downloader.js"); 21 | Fs.copyFile(fromPath,toPath,function (err) { 22 | if(err){ 23 | Editor.error("复制web_downloader.js出错") 24 | } 25 | }); 26 | 27 | } 28 | 29 | let _searthDir = function(dirName,callback){ 30 | if (!Fs.existsSync(dirName)) { 31 | Editor.log(`${dirName} 目录不存在`) 32 | return 33 | } 34 | let files = Fs.readdirSync(dirName); 35 | files.forEach((fileName) => { 36 | let filePath = Path.join(dirName, fileName.toString()); 37 | let stat = Fs.statSync(filePath); 38 | if (stat.isDirectory()) { 39 | _searthDir(filePath,callback); 40 | } else { 41 | callback(fileName,filePath) 42 | } 43 | }); 44 | } 45 | 46 | 47 | /**修改index.html */ 48 | function copyHtml() { 49 | let mainJsName = "main.js" 50 | let settingJsName = "settings.js" 51 | let physicsJsName = "physics-min.js" 52 | let cocos2dJsName = "cocos2d-js-min.js" 53 | let styleDesktopName = "style-desktop.css" 54 | let styleMobileName = "style-mobile.css" 55 | let splashName = "splash.png" 56 | let icoName = "favicon.ico" 57 | _searthDir(buildFloderPath,function (fileName,path) { 58 | if(/main\.([0-9 a-z]|\.)*js/.test(fileName)){ 59 | mainJsName = fileName; 60 | }else if(/physics(-min)?\.([0-9 a-z]|\.)*js/.test(fileName)){ 61 | physicsJsName = fileName; 62 | }else if(/settings\.([0-9 a-z]|\.)*js/.test(fileName)){ 63 | settingJsName = fileName; 64 | }else if(/cocos2d-js(-min)?\.([0-9 a-z]|\.)*js/.test(fileName)){ 65 | cocos2dJsName = fileName; 66 | }else if(/style-desktop\.([0-9 a-z]|\.)*css/.test(fileName)){ 67 | styleDesktopName = fileName; 68 | }else if(/style-mobile\.([0-9 a-z]|\.)*css/.test(fileName)){ 69 | styleMobileName = fileName; 70 | }else if(/favicon\.([0-9 a-z]|\.)*ico/.test(fileName)){ 71 | icoName = fileName; 72 | }else if(/splash\.([0-9 a-z]|\.)*png/.test(fileName)){ 73 | splashName = fileName; 74 | } 75 | }) 76 | 77 | let fromPath = Editor.url("packages://hyz-encript/panel/template_web_index.html","utf-8"); 78 | let toPath = Path.join(buildFloderPath,"index.html"); 79 | 80 | let htmlStr = Fs.readFileSync(fromPath,"utf-8"); 81 | htmlStr = htmlStr.replace('hyz.register_decripted_downloader(tmp_encriptSign,tmp_encriptKey,tmp_needMixFilename,tmp_nameMixSign);',`hyz.register_decripted_downloader('${encriptSign}','${encriptKey}',${needMixFilename},'${nameMixSign}');`) 82 | htmlStr = htmlStr.replace("main.js",mainJsName) 83 | htmlStr = htmlStr.replace("settings.js",settingJsName) 84 | if(physicsJsName.includes("min")){ 85 | htmlStr = htmlStr.replace("physics-min.js",physicsJsName) 86 | }else{ 87 | htmlStr = htmlStr.replace("physics.js",physicsJsName) 88 | } 89 | if(cocos2dJsName.includes("min")){ 90 | htmlStr = htmlStr.replace("cocos2d-js-min.js",cocos2dJsName) 91 | }else{ 92 | htmlStr = htmlStr.replace("cocos2d-js.js",cocos2dJsName) 93 | } 94 | 95 | 96 | htmlStr = htmlStr.replace("style-desktop.css",styleDesktopName) 97 | htmlStr = htmlStr.replace("favicon.ico",icoName) 98 | htmlStr = htmlStr.replace("style-mobile.css",styleMobileName) 99 | htmlStr = htmlStr.replace("splash.png",splashName) 100 | // Editor.log(htmlStr) 101 | Fs.writeFileSync(toPath,htmlStr) 102 | } 103 | 104 | module.exports = function applyWeb({_buildFloderPath,_encriptSign,_encriptKey,_needMixFilename,_nameMixSign}) { 105 | buildFloderPath = _buildFloderPath 106 | encriptSign = _encriptSign 107 | encriptKey = _encriptKey 108 | needMixFilename = _needMixFilename 109 | nameMixSign = _nameMixSign 110 | 111 | copyHelper(); 112 | copyHtml(); 113 | } -------------------------------------------------------------------------------- /panel/encripter.js: -------------------------------------------------------------------------------- 1 | let Fs = require('fs'); 2 | let Path = require('path'); 3 | require("./md5_util") 4 | 5 | /**ArrayBuffer加密解密 */ 6 | class EncriptTool{ 7 | constructor(encriptKey,encriptSign){ 8 | this.setKeySign(encriptKey,encriptSign); 9 | } 10 | 11 | encriptSign = ""; 12 | encriptKey = ""; 13 | setKeySign(encriptKey,encriptSign){ 14 | this.encriptKey = encriptKey; 15 | this.encriptSign = encriptSign; 16 | } 17 | 18 | strToBytes(str){ 19 | let size = str.length; 20 | let result = []; 21 | for(let i=0;i=keyBytes.length){ 61 | idx = 0 62 | } 63 | outBuffer[signBuf.length+i] = eb 64 | } 65 | 66 | return outBuffer; 67 | } 68 | 69 | decodeArrayBuffer(arrbuf,sign=this.encriptSign,key=this.encriptKey){ 70 | if(!this.checkIsEncripted(arrbuf,sign)){ 71 | return arrbuf; 72 | } 73 | let signBuf = new Uint8Array(this.strToBytes(sign)); 74 | let keyBytes = this.strToBytes(key); 75 | let buffer = new Uint8Array(arrbuf); 76 | 77 | let size = buffer.length-signBuf.length; 78 | let _outArrBuf = new ArrayBuffer(size) 79 | let outBuffer = new Uint8Array(_outArrBuf) 80 | let idx = 0; 81 | for(let i=0;i=keyBytes.length){ 85 | idx = 0 86 | } 87 | outBuffer[i] = db; 88 | } 89 | 90 | return outBuffer; 91 | } 92 | } 93 | 94 | /**构建类型 */ 95 | var BuildTypeEnum = { 96 | web_desktop: 0, 97 | web_mobile: 1, 98 | jsb_link: 2, 99 | }; 100 | 101 | 102 | module.exports = class Tools{ 103 | buildType = BuildTypeEnum.web_desktop; 104 | /**构建目录 */ 105 | buildFloderPath = ""; 106 | /**计数 */ 107 | encriptFinishNum = 0; 108 | /**加密后缀名排除列表 */ 109 | encript_ignore_extList = ["mp3","ogg","wav"]; 110 | /**是否要混淆文件名 */ 111 | needMixFilename = true; 112 | /**名称混淆后缀名排除列表 */ 113 | changeName_ignore_extList = ["js","jsc"]; 114 | 115 | _encriptTool = new EncriptTool(); 116 | constructor({buildType,buildFloderPath,encriptKey,encriptSign,needMixFilename=true,nameMixSign=""}){ 117 | this.buildType = buildType; 118 | this.buildFloderPath = buildFloderPath; 119 | this.needMixFilename = needMixFilename; 120 | this.nameMixSign = nameMixSign; 121 | 122 | this._encriptTool.setKeySign(encriptKey,encriptSign); 123 | if(this.buildType==BuildTypeEnum.web_desktop||this.buildType==BuildTypeEnum.web_mobile){ 124 | ///web平台,只加密文本、图片 125 | this.encript_ignore_extList = [ 126 | "js","jsc", 127 | "mp3","ogg","wav","m4a", 128 | "font","eot","ttf","woff","svg","ttc", 129 | "mp4","avi","mov","mpg","mpeg","rm","rmvb" 130 | ]; 131 | }else if(this.buildType==BuildTypeEnum.jsb_link){ 132 | ///jsb 133 | this.encript_ignore_extList = [ 134 | "mp3","ogg","wav","m4a", 135 | ]; 136 | } 137 | 138 | 139 | } 140 | 141 | startBuild(){ 142 | let assetsPath = Path.join(this.buildFloderPath,"assets") 143 | this.encriptDir_(assetsPath); 144 | if(this.buildType==BuildTypeEnum.jsb_link){ 145 | require("./apply_jsb")({ 146 | _changeName_ignore_extList:this.changeName_ignore_extList, 147 | _buildFloderPath:this.buildFloderPath, 148 | _encriptSign:this._encriptTool.encriptSign, 149 | _encriptKey:this._encriptTool.encriptKey, 150 | _needMixFilename:this.needMixFilename, 151 | _nameMixSign:this.nameMixSign 152 | }); 153 | let jsb_adapterPath = Path.join(this.buildFloderPath,"jsb-adapter") 154 | let srcPath = Path.join(this.buildFloderPath,"src") 155 | let mainJsPath = Path.join(this.buildFloderPath,"main.js") 156 | this.encriptDir_(jsb_adapterPath) 157 | this.encriptDir_(srcPath) 158 | this.encodeFile_(mainJsPath) 159 | }else if(this.buildType==BuildTypeEnum.web_desktop||this.buildType==BuildTypeEnum.web_mobile){ 160 | // Editor.log("--------加密web") 161 | require("./apply_web")({ 162 | _buildFloderPath:this.buildFloderPath, 163 | _encriptSign:this._encriptTool.encriptSign, 164 | _encriptKey:this._encriptTool.encriptKey, 165 | _needMixFilename:this.needMixFilename, 166 | _nameMixSign:this.nameMixSign, 167 | }); 168 | } 169 | } 170 | 171 | changeName_(filePath) { 172 | if(!this.needMixFilename){ 173 | return filePath 174 | } 175 | let ext = Path.extname(filePath); 176 | if(this.changeName_ignore_extList.indexOf(ext.slice(1))>=0){ 177 | return filePath; 178 | } 179 | let name = Path.basename(filePath);//文件名 180 | let ret = filePath; 181 | 182 | if(name[8]=="-"&&name[13]=="-"&&name[18]=="-"&&name[23]=="-"){ 183 | let md5 = hyz.str_to_md5(name+this.nameMixSign) 184 | let arr = [8,13,18,23] 185 | for(let i = arr.length-1;i>=0;i--){ 186 | let idx = arr[i]; 187 | md5 = md5.slice(0, idx) + "-" + md5.slice(idx); 188 | } 189 | md5+=ext; 190 | 191 | ret = ret.replace(name.slice(0,2)+"/"+name,md5.slice(0,2)+"/"+md5); 192 | ret = ret.replace(name.slice(0,2)+"\\"+name,md5.slice(0,2)+"\\"+md5); 193 | let dir = Path.dirname(ret); 194 | 195 | if(!Fs.existsSync(dir)){ 196 | Fs.mkdirSync(dir) 197 | } 198 | } 199 | // Editor.log("--------改名",this.nameMixSign||"nil",filePath,"==>>",ret) 200 | return ret; 201 | } 202 | 203 | /**加密文件夹 */ 204 | encriptDir_(dirName){ 205 | if (!Fs.existsSync(dirName)) { 206 | Editor.log(`${dirName} 目录不存在`) 207 | return 208 | } 209 | let files = Fs.readdirSync(dirName); 210 | files.forEach((fileName) => { 211 | // Editor.log("-----aaaa",fileName) 212 | let filePath = Path.join(dirName, fileName.toString()); 213 | let stat = Fs.statSync(filePath); 214 | if (stat.isDirectory()) { 215 | this.encriptDir_(filePath); 216 | } else { 217 | this.encodeFile_(filePath) 218 | } 219 | }); 220 | } 221 | 222 | /**加密文件 */ 223 | encodeFile_(filePath) { 224 | let ext = Path.extname(filePath); 225 | if(this.encript_ignore_extList.indexOf(ext.slice(1))>=0){ 226 | return; 227 | } 228 | 229 | let newPath = this.changeName_(filePath) 230 | // Editor.log("-------加密",filePath,newPath); 231 | let inbuffer = Fs.readFileSync(filePath); 232 | 233 | if(this._encriptTool.checkIsEncripted(inbuffer)){ 234 | // Editor.log("已经加密过",filePath) 235 | return 236 | } 237 | 238 | let outBuffer = this._encriptTool.encodeArrayBuffer(inbuffer) 239 | Fs.unlinkSync(filePath) 240 | Fs.writeFileSync(newPath,outBuffer) 241 | this.encriptFinishNum = this.encriptFinishNum + 1 242 | } 243 | } -------------------------------------------------------------------------------- /panel/index.css: -------------------------------------------------------------------------------- 1 | :host { 2 | display: flex; 3 | flex-direction: column; 4 | } 5 | 6 | h2 { 7 | color: #f90; 8 | font-size: 15px; 9 | width: 600px; 10 | text-align: center 11 | } 12 | .middle { 13 | width: 600px; 14 | align-items: center; 15 | } 16 | .inputstyle { 17 | width: 600px; 18 | } 19 | .okstyle { 20 | margin-top: 100px; 21 | margin-left: 250px; 22 | width: 100px; 23 | color: #f90; 24 | text-align: center; 25 | } 26 | -------------------------------------------------------------------------------- /panel/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

配置面板

5 |
6 | 7 |
8 |

构建选项

9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 | 加密 23 |
24 | -------------------------------------------------------------------------------- /panel/index.js: -------------------------------------------------------------------------------- 1 | let Fs = require('fs'); 2 | let Path = require('path'); 3 | 4 | // panel/index.js, this filename needs to match the one registered in package.json 5 | Editor.Panel.extend({ 6 | // css style for panel 7 | style: Fs.readFileSync(Editor.url('packages://hyz-encript/panel/index.css', 'utf8')), 8 | 9 | // html template for panel 10 | template: Fs.readFileSync(Editor.url('packages://hyz-encript/panel/index.html', 'utf8')), 11 | 12 | // element and variable binding 13 | $: { 14 | btn: '#btn', 15 | buildType:"#buildType", 16 | buildFloder:"#buildFloder", 17 | input_encriptKey: "#input_encriptKey", 18 | input_encriptSign: "#input_encriptSign", 19 | needMixFilename: "#needMixFilename", 20 | input_nameMixSign: "#input_nameMixSign", 21 | }, 22 | 23 | /**是否要混淆文件名 */ 24 | get _needMixFilename(){ 25 | return this.$needMixFilename.value 26 | }, 27 | /**混淆签名 */ 28 | get _nameMixSign(){ 29 | return this.$input_nameMixSign.value 30 | }, 31 | /**加密签名 */ 32 | get _encriptSign(){ 33 | return this.$input_encriptSign.value 34 | }, 35 | /**加密密码 */ 36 | get _encriptKey(){ 37 | return this.$input_encriptKey.value 38 | }, 39 | /**构建目录 */ 40 | get _buildFloder(){ 41 | return this.$buildFloder.value 42 | }, 43 | /**构建类型 */ 44 | get _buildType(){ 45 | return this.$buildType.value 46 | }, 47 | 48 | // method executed when template and styles are successfully loaded and initialized 49 | ready () { 50 | this.recordPath = Editor.url('packages://hyz-encript/panel/record.json', 'utf8'); 51 | 52 | // Editor.log('--------插件准备好',recordPath); 53 | let record = {}; 54 | if(Fs.existsSync(this.recordPath)){ 55 | record = JSON.parse(Fs.readFileSync(this.recordPath)); 56 | 57 | if(record.encriptSign){ 58 | this.$input_encriptSign.value = record.encriptSign; 59 | } 60 | if(record.encriptKey){ 61 | this.$input_encriptKey.value = record.encriptKey; 62 | } 63 | if(record.buildType!=undefined){ 64 | this.$buildType.value = record.buildType; 65 | } 66 | if(record.needMixFilename){ 67 | this.$needMixFilename.value = record.needMixFilename; 68 | } 69 | this.$input_nameMixSign.disabled = !this._needMixFilename; 70 | if(record.nameMixSign&&this._needMixFilename){ 71 | this.$input_nameMixSign.value = record.nameMixSign; 72 | } 73 | 74 | // Editor.log("有记录",record) 75 | }else{ 76 | 77 | } 78 | 79 | this.$buildFloder.value = this._getBuildPath(); 80 | 81 | this.$buildType.addEventListener('change',()=>{ 82 | this.$buildFloder.value = this._getBuildPath(); 83 | }) 84 | 85 | this.$needMixFilename.addEventListener('change',()=>{ 86 | this.$input_nameMixSign.disabled = !this._needMixFilename; 87 | if(record.nameMixSign&&this._needMixFilename){ 88 | this.$input_nameMixSign.value = record.nameMixSign; 89 | } 90 | }) 91 | 92 | this.$btn.addEventListener('confirm', this._doEncript.bind(this)); 93 | }, 94 | 95 | _doEncript(){ 96 | let CLASS = require("./encripter") 97 | let record = { 98 | buildType : this._buildType, 99 | buildFloderPath : this._getBuildPath(), 100 | recordPath : this.recordPath, 101 | encriptKey : this._encriptKey, 102 | encriptSign : this._encriptSign, 103 | needMixFilename : this._needMixFilename, 104 | nameMixSign:this._nameMixSign, 105 | } 106 | let tool = new CLASS(record); 107 | tool.startBuild(); 108 | 109 | Fs.writeFileSync(this.recordPath,JSON.stringify(record)) 110 | Editor.log('--------------加密完成') 111 | }, 112 | 113 | _getBuildPath(){ 114 | let buildType = this._buildType; 115 | let assetsPath = Editor.url('db://assets','utf8'); 116 | let web_desktopPath = Path.join(assetsPath,"../build/web-desktop"); 117 | let web_mobilePath = Path.join(assetsPath,"../build/web-mobile"); 118 | let jsb_linkPath = Path.join(assetsPath,"../build/jsb-link"); 119 | if(buildType==0){ 120 | return web_desktopPath; 121 | }else if(buildType==1){ 122 | return web_mobilePath; 123 | }else if(buildType==2){ 124 | return jsb_linkPath; 125 | } 126 | }, 127 | 128 | // register your ipc messages here 129 | messages: { 130 | 131 | }, 132 | 133 | }); 134 | -------------------------------------------------------------------------------- /panel/md5_util.js: -------------------------------------------------------------------------------- 1 | function str_to_md5(string){ 2 | function md5_RotateLeft(lValue, iShiftBits) { 3 | return (lValue<>>(32-iShiftBits)); 4 | } 5 | function md5_AddUnsigned(lX,lY){ 6 | var lX4,lY4,lX8,lY8,lResult; 7 | lX8 = (lX & 0x80000000); 8 | lY8 = (lY & 0x80000000); 9 | lX4 = (lX & 0x40000000); 10 | lY4 = (lY & 0x40000000); 11 | lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF); 12 | if (lX4 & lY4) { 13 | return (lResult ^ 0x80000000 ^ lX8 ^ lY8); 14 | } 15 | if (lX4 | lY4) { 16 | if (lResult & 0x40000000) { 17 | return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); 18 | } else { 19 | return (lResult ^ 0x40000000 ^ lX8 ^ lY8); 20 | } 21 | } else { 22 | return (lResult ^ lX8 ^ lY8); 23 | } 24 | } 25 | function md5_F(x,y,z){ 26 | return (x & y) | ((~x) & z); 27 | } 28 | function md5_G(x,y,z){ 29 | return (x & z) | (y & (~z)); 30 | } 31 | function md5_H(x,y,z){ 32 | return (x ^ y ^ z); 33 | } 34 | function md5_I(x,y,z){ 35 | return (y ^ (x | (~z))); 36 | } 37 | function md5_FF(a,b,c,d,x,s,ac){ 38 | a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_F(b, c, d), x), ac)); 39 | return md5_AddUnsigned(md5_RotateLeft(a, s), b); 40 | }; 41 | function md5_GG(a,b,c,d,x,s,ac){ 42 | a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_G(b, c, d), x), ac)); 43 | return md5_AddUnsigned(md5_RotateLeft(a, s), b); 44 | }; 45 | function md5_HH(a,b,c,d,x,s,ac){ 46 | a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_H(b, c, d), x), ac)); 47 | return md5_AddUnsigned(md5_RotateLeft(a, s), b); 48 | }; 49 | function md5_II(a,b,c,d,x,s,ac){ 50 | a = md5_AddUnsigned(a, md5_AddUnsigned(md5_AddUnsigned(md5_I(b, c, d), x), ac)); 51 | return md5_AddUnsigned(md5_RotateLeft(a, s), b); 52 | }; 53 | function md5_ConvertToWordArray(string) { 54 | var lWordCount; 55 | var lMessageLength = string.length; 56 | var lNumberOfWords_temp1=lMessageLength + 8; 57 | var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64; 58 | var lNumberOfWords = (lNumberOfWords_temp2+1)*16; 59 | var lWordArray=Array(lNumberOfWords-1); 60 | var lBytePosition = 0; 61 | var lByteCount = 0; 62 | while ( lByteCount < lMessageLength ) { 63 | lWordCount = (lByteCount-(lByteCount % 4))/4; 64 | lBytePosition = (lByteCount % 4)*8; 65 | lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<>>29; 73 | return lWordArray; 74 | }; 75 | function md5_WordToHex(lValue){ 76 | var WordToHexValue="",WordToHexValue_temp="",lByte,lCount; 77 | for(lCount = 0;lCount<=3;lCount++){ 78 | lByte = (lValue>>>(lCount*8)) & 255; 79 | WordToHexValue_temp = "0" + lByte.toString(16); 80 | WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2); 81 | } 82 | return WordToHexValue; 83 | }; 84 | function md5_Utf8Encode(string){ 85 | string = string.replace(/\r\n/g,"\n"); 86 | var utftext = ""; 87 | for (var n = 0; n < string.length; n++) { 88 | var c = string.charCodeAt(n); 89 | if (c < 128) { 90 | utftext += String.fromCharCode(c); 91 | }else if((c > 127) && (c < 2048)) { 92 | utftext += String.fromCharCode((c >> 6) | 192); 93 | utftext += String.fromCharCode((c & 63) | 128); 94 | } else { 95 | utftext += String.fromCharCode((c >> 12) | 224); 96 | utftext += String.fromCharCode(((c >> 6) & 63) | 128); 97 | utftext += String.fromCharCode((c & 63) | 128); 98 | } 99 | } 100 | return utftext; 101 | }; 102 | var x=Array(); 103 | var k,AA,BB,CC,DD,a,b,c,d; 104 | var S11=7, S12=12, S13=17, S14=22; 105 | var S21=5, S22=9 , S23=14, S24=20; 106 | var S31=4, S32=11, S33=16, S34=23; 107 | var S41=6, S42=10, S43=15, S44=21; 108 | string = md5_Utf8Encode(string); 109 | x = md5_ConvertToWordArray(string); 110 | a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476; 111 | for (k=0;k 2 | 3 | 4 | 5 | 6 | Cocos Creator | hello_world 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |

hello_world

24 | 25 |
26 | 27 |
28 |
29 | 30 |
31 |
32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /panel/web_downloader.js: -------------------------------------------------------------------------------- 1 | 2 | function parseParameters (options, onProgress, onComplete) { 3 | if (onComplete === undefined) { 4 | var isCallback = typeof options === 'function'; 5 | if (onProgress) { 6 | onComplete = onProgress; 7 | if (!isCallback) { 8 | onProgress = null; 9 | } 10 | } 11 | else if (onProgress === undefined && isCallback) { 12 | onComplete = options; 13 | options = null; 14 | onProgress = null; 15 | } 16 | if (onProgress !== undefined && isCallback) { 17 | onProgress = options; 18 | options = null; 19 | } 20 | } 21 | options = options || Object.create(null); 22 | return { options, onProgress, onComplete }; 23 | } 24 | 25 | /**ArrayBuffer转字符串 */ 26 | function arrayBuffer2Text(buffer,onComplete) { 27 | var b = new Blob([buffer]); 28 | var r = new FileReader(); 29 | r.readAsText(b, 'utf-8'); 30 | r.onload = function (){ 31 | onComplete&&onComplete(null,r.result) 32 | } 33 | r.onerror = function (e) { 34 | onComplete&&onComplete(r.error,r.result) 35 | } 36 | } 37 | 38 | function arrayBufferToBase64Img(buffer){ 39 | const str = String.fromCharCode(...new Uint8Array(buffer)); 40 | return window.btoa(str); 41 | } 42 | 43 | 44 | function downloadFile (url, options, onProgress, onComplete) { 45 | var { options, onProgress, onComplete } = parseParameters(options, onProgress, onComplete); 46 | 47 | var xhr = new XMLHttpRequest(), errInfo = 'download failed: ' + url + ', status: '; 48 | 49 | xhr.open('GET', url, true); 50 | 51 | if (options.responseType !== undefined) xhr.responseType = options.responseType; 52 | if (options.withCredentials !== undefined) xhr.withCredentials = options.withCredentials; 53 | if (options.mimeType !== undefined && xhr.overrideMimeType ) xhr.overrideMimeType(options.mimeType); 54 | if (options.timeout !== undefined) xhr.timeout = options.timeout; 55 | 56 | if (options.header) { 57 | for (var header in options.header) { 58 | xhr.setRequestHeader(header, options.header[header]); 59 | } 60 | } 61 | 62 | xhr.onload = function () { 63 | if ( xhr.status === 200 || xhr.status === 0 ) { 64 | onComplete && onComplete(null, xhr.response); 65 | } else { 66 | onComplete && onComplete(new Error(errInfo + xhr.status + '(no response)')); 67 | } 68 | 69 | }; 70 | 71 | if (onProgress) { 72 | xhr.onprogress = function (e) { 73 | if (e.lengthComputable) { 74 | onProgress(e.loaded, e.total); 75 | } 76 | }; 77 | } 78 | 79 | xhr.onerror = function(){ 80 | onComplete && onComplete(new Error(errInfo + xhr.status + '(error)')); 81 | }; 82 | 83 | xhr.ontimeout = function(){ 84 | onComplete && onComplete(new Error(errInfo + xhr.status + '(time out)')); 85 | }; 86 | 87 | xhr.onabort = function(){ 88 | onComplete && onComplete(new Error(errInfo + xhr.status + '(abort)')); 89 | }; 90 | 91 | xhr.send(null); 92 | 93 | return xhr; 94 | } 95 | 96 | function _getRealPath(path) { 97 | let excludeChangeNameList = [".mp3",".ogg",".wav",".js",".jsc",] 98 | if(path.indexOf("assets")!=0){ 99 | return path 100 | } 101 | if(!needMixFilename){//tag 102 | return path; 103 | } 104 | for(let ext of excludeChangeNameList){ 105 | if(path.endsWith(ext)){ 106 | return path 107 | } 108 | } 109 | var ext = path.substr(path.lastIndexOf(".")); 110 | var arr = path.split('/'); 111 | let name = arr[arr.length-1]; 112 | let realPath = path; 113 | 114 | if(name[8]=="-"&&name[13]=="-"&&name[18]=="-"&&name[23]=="-"){ 115 | let md5 = hyz.str_to_md5(name+nameMixSign) 116 | let arr2 = [8,13,18,23] 117 | for(let i = arr2.length-1;i>=0;i--){ 118 | let idx = arr2[i]; 119 | md5 = md5.slice(0, idx) + "-" + md5.slice(idx); 120 | } 121 | md5+=ext; 122 | 123 | realPath = path.replace(name,md5); 124 | realPath = realPath.replace("/"+name.slice(0,2)+"/","/"+md5.slice(0,2)+"/"); 125 | realPath = realPath.replace("\\"+name.slice(0,2)+"\\","\\"+md5.slice(0,2)+"\\"); 126 | } 127 | 128 | return realPath 129 | }; 130 | 131 | function downloadArrayBuffer (url, options, onComplete) { 132 | options.responseType = "arraybuffer"; 133 | url = _getRealPath(url) 134 | downloadFile(url, options, options.onFileProgress, function (err,data) { 135 | if(!err){ 136 | ///解密 137 | data = _decriptTool.decodeArrayBuffer(data); 138 | } 139 | onComplete&&onComplete(err,data) 140 | }); 141 | }; 142 | 143 | function downloadText (url, options, onComplete) { 144 | downloadArrayBuffer(url,options,function (err,data) { 145 | if(err){ 146 | onComplete&&onComplete(err,data) 147 | }else{ 148 | ///转化成Text 149 | arrayBuffer2Text(data,function(err,text) { 150 | if(err){ 151 | onComplete&&onComplete(err,data) 152 | }else{ 153 | onComplete&&onComplete(null,text) 154 | } 155 | }) 156 | } 157 | }) 158 | }; 159 | 160 | function downloadJson(url, options, onComplete) { 161 | downloadText(url,options,function (err,data) { 162 | if(err){ 163 | onComplete&&onComplete(err,data) 164 | return; 165 | } 166 | if (!err && typeof data === 'string') { 167 | try { 168 | data = JSON.parse(data); 169 | } 170 | catch (e) { 171 | err = e; 172 | } 173 | } 174 | onComplete && onComplete(err, data); 175 | }) 176 | } 177 | 178 | function downloadDomImage (url, options, onComplete) { 179 | var { options, onComplete } = parseParameters(options, undefined, onComplete); 180 | 181 | var img = new Image(); 182 | 183 | if (window.location.protocol !== 'file:') { 184 | img.crossOrigin = 'anonymous'; 185 | } 186 | 187 | function loadCallback () { 188 | img.removeEventListener('load', loadCallback); 189 | img.removeEventListener('error', errorCallback); 190 | onComplete && onComplete(null, img); 191 | } 192 | 193 | function errorCallback () { 194 | img.removeEventListener('load', loadCallback); 195 | img.removeEventListener('error', errorCallback); 196 | onComplete && onComplete(new Error(cc.debug.getError(4930, url))); 197 | } 198 | 199 | img.addEventListener('load', loadCallback); 200 | img.addEventListener('error', errorCallback); 201 | img.src = url; 202 | return img; 203 | } 204 | 205 | 206 | const imgTypes = { 207 | "png":"image/png", 208 | "jpg":"image/jpg", 209 | "jpeg":"image/jpeg", 210 | } 211 | 212 | function downloadImage(url, options, onComplete) { 213 | downloadArrayBuffer(url,options,function(err, data){ 214 | if(err){ 215 | onComplete&&onComplete(null,data); 216 | return; 217 | } 218 | let index = url.lastIndexOf("."); 219 | let suffix = url.substr(index+1); 220 | let typeStr = imgTypes[suffix]||imgTypes["png"] 221 | 222 | if(cc.sys.capabilities.imageBitmap){ 223 | let blob = new Blob([data],{type:typeStr}) 224 | onComplete&&onComplete(null,blob); 225 | }else{ 226 | let base64code = arrayBufferToBase64Img(data); 227 | base64code = `data:${typeStr};base64,${base64code}` 228 | downloadDomImage(base64code,options,onComplete) 229 | } 230 | }) 231 | }; 232 | 233 | const downloaded = {}; 234 | 235 | function downloadScript (url, options, onComplete) { 236 | var { options, onComplete } = parseParameters(options, undefined, onComplete); 237 | 238 | // no need to load script again 239 | if (downloaded[url]) { 240 | return onComplete && onComplete(null); 241 | } 242 | 243 | var d = document, s = document.createElement('script'); 244 | 245 | if (window.location.protocol !== 'file:') { 246 | s.crossOrigin = 'anonymous'; 247 | } 248 | 249 | s.async = options.async; 250 | s.src = url; 251 | function loadHandler () { 252 | s.parentNode.removeChild(s); 253 | s.removeEventListener('load', loadHandler, false); 254 | s.removeEventListener('error', errorHandler, false); 255 | downloaded[url] = true; 256 | onComplete && onComplete(null); 257 | } 258 | 259 | function errorHandler() { 260 | s.parentNode.removeChild(s); 261 | s.removeEventListener('load', loadHandler, false); 262 | s.removeEventListener('error', errorHandler, false); 263 | onComplete && onComplete(new Error(cc.debug.getError(4928, url))); 264 | } 265 | 266 | s.addEventListener('load', loadHandler, false); 267 | s.addEventListener('error', errorHandler, false); 268 | d.body.appendChild(s); 269 | } 270 | 271 | const REGEX = /^(?:\w+:\/\/|\.+\/).+/; 272 | var downloadBundle = function (nameOrUrl, options, onComplete) { 273 | let bundleName = cc.path.basename(nameOrUrl); 274 | let url = nameOrUrl; 275 | if (!REGEX.test(url)) url = 'assets/' + bundleName; 276 | var version = options.version ||cc.assetManager.downloader.bundleVers[bundleName]; 277 | var count = 0; 278 | var config = `${url}/config.${version ? version + '.' : ''}json`; 279 | let out = null, error = null; 280 | downloadJson(config, options, function (err, response) { 281 | if (err) { 282 | error = err; 283 | } 284 | out = response; 285 | out && (out.base = url + '/'); 286 | count++; 287 | if (count === 2) { 288 | onComplete(error, out); 289 | } 290 | }); 291 | 292 | var js = `${url}/index.${version ? version + '.' : ''}js`; 293 | downloadScript(js, options, function (err) { 294 | if (err) { 295 | error = err; 296 | } 297 | count++; 298 | if (count === 2) { 299 | onComplete(error, out); 300 | } 301 | }); 302 | }; 303 | 304 | var downloaders = { 305 | // Images 306 | '.png' : downloadImage, 307 | '.jpg' : downloadImage, 308 | '.bmp' : downloadImage, 309 | '.jpeg' : downloadImage, 310 | '.gif' : downloadImage, 311 | '.ico' : downloadImage, 312 | '.tiff' : downloadImage, 313 | '.webp' : downloadImage, 314 | '.image' : downloadImage, 315 | '.pvr' : downloadArrayBuffer, 316 | '.pkm' : downloadArrayBuffer, 317 | 318 | // Audio 319 | // '.mp3' : downloadAudio, 320 | // '.ogg' : downloadAudio, 321 | // '.wav' : downloadAudio, 322 | // '.m4a' : downloadAudio, 323 | 324 | // Txt 325 | '.txt' : downloadText, 326 | '.xml' : downloadText, 327 | '.vsh' : downloadText, 328 | '.fsh' : downloadText, 329 | '.atlas' : downloadText, 330 | 331 | '.tmx' : downloadText, 332 | '.tsx' : downloadText, 333 | 334 | '.json' : downloadJson, 335 | '.ExportJson' : downloadJson, 336 | '.plist' : downloadText, 337 | 338 | '.fnt' : downloadText, 339 | 340 | // font 341 | // '.font' : loadFont, 342 | // '.eot' : loadFont, 343 | // '.ttf' : loadFont, 344 | // '.woff' : loadFont, 345 | // '.svg' : loadFont, 346 | // '.ttc' : loadFont, 347 | 348 | // // Video 349 | // '.mp4': downloadVideo, 350 | // '.avi': downloadVideo, 351 | // '.mov': downloadVideo, 352 | // '.mpg': downloadVideo, 353 | // '.mpeg': downloadVideo, 354 | // '.rm': downloadVideo, 355 | // '.rmvb': downloadVideo, 356 | 357 | // Binary 358 | '.binary' : downloadArrayBuffer, 359 | '.bin': downloadArrayBuffer, 360 | '.dbbin': downloadArrayBuffer, 361 | '.skel': downloadArrayBuffer, 362 | 363 | 'bundle': downloadBundle, 364 | 365 | 'default': downloadText 366 | }; 367 | 368 | /**ArrayBuffer加密解密 */ 369 | class DecriptTool{ 370 | constructor(encriptKey,encriptSign){ 371 | this.setKeySign(encriptKey,encriptSign); 372 | } 373 | 374 | encriptSign = ""; 375 | encriptKey = ""; 376 | setKeySign(encriptKey,encriptSign){ 377 | this.encriptKey = encriptKey; 378 | this.encriptSign = encriptSign; 379 | } 380 | 381 | strToBytes(str){ 382 | let size = str.length; 383 | let result = []; 384 | for(let i=0;i=keyBytes.length){ 421 | idx = 0 422 | } 423 | outBuffer[i] = db; 424 | } 425 | 426 | return outBuffer; 427 | } 428 | } 429 | 430 | var _decriptTool = new DecriptTool(); 431 | 432 | var needMixFilename = false; 433 | var nameMixSign = ""; 434 | 435 | window.hyz = window.hyz || {}; 436 | let hyz = window.hyz; 437 | 438 | hyz.register_decripted_downloader = function register_decripted_downloader(_encriptSign,_encriptKey,_needMixFilename,_nameMixSign) { 439 | _decriptTool.setKeySign(_encriptKey,_encriptSign) 440 | needMixFilename = _needMixFilename 441 | nameMixSign = _nameMixSign 442 | for(let key in downloaders){ 443 | cc.assetManager.downloader.register(key,downloaders[key]) 444 | } 445 | } --------------------------------------------------------------------------------