cocos creator資源加密(支持web和native)

上期文章研究了資源加載流程,資源加載流程中,讀取資源數(shù)據(jù)是在download過程中,如果我們要對資源進行解密,要改的就是這里了。

我做了一個加密插件:


image.png

支持對web平臺和native平臺進行加密,支持對文件名進行混淆。

上篇文章講的都是web平臺的流程,對于native平臺,下載流程是不一樣的,使用的是c++端導(dǎo)出的多線程下載,適配代碼在jsb-engine.js中:
image.png

c++端讀取文件全都是通過FileUtils::getStringFromFile或者FileUtils::getDataFromFile進行操作,我們解密統(tǒng)一在這兩個函數(shù)里進行就可以了。


image.png

對于web平臺的解密,正常情況下,應(yīng)該通過cc.assetManager.downloader.register注冊不同的下載方法。但是為了不破壞源工程,我選擇修改構(gòu)建后導(dǎo)出的cocos2d-js.js文件,主要是修改有三點,解密代碼放在downloadArrayBuffer,修改downloadText和downloadImage,改為通過downloadArrayBuffer先下載二進制流再解密解碼為文本或圖片。

var downloadArrayBuffer = function downloadArrayBuffer(url, options, onComplete) {
    options.responseType = "arraybuffer";
    url = _getRealPath(url)
    downloadFile(url, options, options.onFileProgress, function (err,data) {
        if(!err){
            ///解密
            data = hyz._decriptTool.decodeArrayBuffer(data);
        }
        onComplete&&onComplete(err,data)
    });
};
var downloadText = function downloadText (url, options, onComplete) {
    downloadArrayBuffer(url,options,function (err,data) {
    if(err){
        onComplete&&onComplete(err,data)
    }else{
        ///轉(zhuǎn)化成Text
        hyz.arrayBuffer2Text(data,function(err,text) {
        if(err){
            onComplete&&onComplete(err,text)
        }else{
            onComplete&&onComplete(null,text)
        }
        })
    }
    })
};
var downloadJson = function downloadJson(url, options, onComplete) {
    downloadText(url,options,function (err,data) {
    if(err){
        onComplete&&onComplete(err,data)
        return;
    }
    if (!err && typeof data === 'string') {
        try {
            data = JSON.parse(data);
        }
        catch (e) {
            err = e;
        }
    }
    onComplete && onComplete(err, data);
    })
};
var downloadImage = function downloadImage(url, options, onComplete) {
    downloadArrayBuffer(url,options,function(err, data){
    if(err){
        onComplete&&onComplete(null,data);
        return;
    }
    let index = url.lastIndexOf(".");
    let suffix = url.substr(index+1);
    let typeStr = hyz.imgTypes[suffix]||hyz.imgTypes["png"]

    if(cc.sys.capabilities.imageBitmap){
        let blob = new Blob([data],{type:typeStr})
        onComplete&&onComplete(null,blob);
        cc.log(blob)
    }else{
        let base64code = hyz.arrayBufferToBase64Img(data);
        base64code = `data:${typeStr};base64,${base64code}`
        downloadDomImage(base64code,options,onComplete)
    }
    })
};

如上,主要是downloadArrayBuffer進行解密,另一個要注意的就是下載圖片要手動轉(zhuǎn)化一下。

加密解密使用的最簡單的異或加密,代碼如下:

encodeArrayBuffer(arrbuf,sign=this.encriptSign,key=this.encriptKey) {
        if(this.checkIsEncripted(arrbuf,sign)){
            return
        }
        let signBuf = new Uint8Array(this.strToBytes(sign));
        let keyBytes = this.strToBytes(key)
        let buffer = new Uint8Array(arrbuf);
        
        let _outArrBuf = new ArrayBuffer(signBuf.length+buffer.length)
        let outBuffer = new Uint8Array(_outArrBuf)
        for(let i=0;i<signBuf.length;i++){
            outBuffer[i] = signBuf[i]
        }
        let idx = 0;
    
        for(let i=0;i<buffer.length;i++){
            let b = buffer[i];
            let eb = b^keyBytes[idx]
            if(++idx>=keyBytes.length){
                idx = 0
            }
            outBuffer[signBuf.length+i] = eb
        }
        
        return outBuffer;
    }
    
    decodeArrayBuffer(arrbuf,sign=this.encriptSign,key=this.encriptKey){
        if(!this.checkIsEncripted(arrbuf,sign)){
            return arrbuf;
        }
        let signBuf = new Uint8Array(this.strToBytes(sign));
        let keyBytes = this.strToBytes(key);
        let buffer = new Uint8Array(arrbuf);
    
        let size = buffer.length-signBuf.length;
        let _outArrBuf = new ArrayBuffer(size)
        let outBuffer = new Uint8Array(_outArrBuf)
        let idx = 0;
        for(let i=0;i<size;i++){
            let b = buffer[signBuf.length+i];
            let db = b^keyBytes[idx]
            if(++idx>=keyBytes.length){
                idx = 0
            }
            outBuffer[i] = db;
        }
    
        return outBuffer;
    }

至于文件名混淆,就是對源uuid格式的文件名和一個混淆簽名再次進行md5,得到新文件名。
如aaaa-bbbb-cccc-dddd.png變?yōu)?111-2222-3333-4444.png
關(guān)鍵是工程中如何識別新文件名。項目運行時,查找文件是根據(jù)文件路徑查到uuid再組裝成url的,我們只需要在url組裝后,再按照我們的混淆規(guī)則,再算一次就好了,保險起見,只混淆uuid格式的文件名。native模式下,修改jsb-engine.js的transformUrl,對本地url進行再次轉(zhuǎn)換;web模式下,downloadArrayBuffer里直接在下載之前將url轉(zhuǎn)換成混淆后的文件名。

function _getRealPath(path) {
    let excludeChangeNameList = [".mp3",".ogg",".wav",".js",".jsc",]
    if(path.indexOf("assets")!=0){
        return path
    }
  if(!true){//tag
    return path;
  }
    for(let ext of excludeChangeNameList){
      if(path.endsWith(ext)){
          return path
      }
    }
    var ext = path.substr(path.lastIndexOf("."));
    var arr = path.split('/');
    let name = arr[arr.length-1];
    let realPath = path;

    if(name[8]=="-"&&name[13]=="-"&&name[18]=="-"&&name[23]=="-"){
        let md5 = hyz.str_to_md5(name+"ggg5675")
        let arr2 = [8,13,18,23]
        for(let i = arr2.length-1;i>=0;i--){
          let idx = arr2[i];
          md5 = md5.slice(0, idx) + "-" + md5.slice(idx);
        }
        md5+=ext;
    
      realPath = path.replace(name,md5);
      realPath = realPath.replace("/"+name.slice(0,2)+"/","/"+md5.slice(0,2)+"/");
      realPath = realPath.replace("\\"+name.slice(0,2)+"\\","\\"+md5.slice(0,2)+"\\");
    }

    return realPath
};

完整插件源碼在GitHub

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、前言 Cocos Creator 打包后的素材資源,如:圖片,聲音等。默認是保持原始格式,只要遇到破解黨,那么...
    天煞魔獵手閱讀 8,993評論 4 6
  • 用到的組件 1、通過CocoaPods安裝 2、第三方類庫安裝 3、第三方服務(wù) 友盟社會化分享組件 友盟用戶反饋 ...
    SunnyLeong閱讀 15,164評論 1 180
  • ![Flask](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAW...
    極客學(xué)院Wiki閱讀 7,776評論 0 3
  • 不知不覺易趣客已經(jīng)在路上走了快一年了,感覺也該讓更多朋友認識知道易趣客,所以就謝了這篇簡介,已做創(chuàng)業(yè)記事。 易趣客...
    Physher閱讀 3,806評論 1 2
  • 雙胎妊娠有家族遺傳傾向,隨母系遺傳。有研究表明,如果孕婦本人是雙胎之一,她生雙胎的機率為1/58;若孕婦的父親或母...
    鄴水芙蓉hibiscus閱讀 3,886評論 0 2

友情鏈接更多精彩內(nèi)容