CocosCreator图片资源加密解密

CocosCreator图片资源加密解密

文章转载自:http://www.cnblogs.com/pixs-union/p/6226337.html

主要处理png图片,其他格式图片也是一样的原理。阅读前可以简略了解一下png格式图片的Data trunck。
首先使用python脚本去掉png的PNG SIG(8 bytes) 以及末尾的PNGIEND(12 bytes)。然后图片剩余数据的每一个字节和秘钥字符串的每一个字符做不进位加(按位异或,解密的原理就是 a ^ b ^ b = a)。通过改写cpp工程里的 Image::initWithImageData(const unsigned char * data, ssize_t dataLen),来进行还原图片数据,也就是解密,过程就是对每一位加密后的数据按秘钥做异或运算还原数据,然后加上PNGSIG和PNGIEND。

加密脚本:encode.py(这个脚本会生成加密后的图片替换原始图片)

#该脚本用于加密png图片 使用python3以上版本解释执行
__author__ = "ChenGuanzhou"
import os
import time
CUR_DIR = os.getcwd();
print("cur_dir:",CUR_DIR)
#CUR_DIR = 'C:\\Users\\chenguanzhou\\Desktop'
_KEY = 'liangzai123' #指定加密秘钥,英文
_ENCRYSIG = 'liangzai'
_PNGSIG = bytes([0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a])
_PNGIEND = bytes([0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82])
 #获取filesig是否是png
def isPNGSig(bytes_8):
    return bytes_8 == _PNGSIG
 
def isPNG(absPath):#判断是否是PNG图片
    """
    :param absPath: 文件的绝对路径
    :return: {Bool}
    """
    isFile = os.path.isfile(absPath)
    hasPNGSig = False
    fileExt = os.path.splitext(absPath)[1]
    isPngExt = (fileExt == ".png" or fileExt == ".PNG")
    if isFile and isPngExt:
        with open(absPath,"rb") as file:
            hasPNGSig = isPNGSig(file.read(8)[:8])
    return isFile and isPngExt and hasPNGSig
 
def preProcessPng(pngData):#预处理图片数据
    """
    剪掉png的signature(8bytes),IEND(12Bytes)
    :param pngData:
    :return:
    """
    assert type(pngData) == bytes
    lostHeadData = pngData[8:]
    iendData = lostHeadData[-12:]
    if iendData == _PNGIEND:#防止Png已经进行过外部软件的压缩,丢掉了IEND
        return lostHeadData[:-12]
    else:
        return lostHeadData
 
def encryption(fileData,key):#加密操作 ascii占一个字节
    """
    加密png数据
    :param fileData:{bytes}预处理后的png数据
    :param key:{str}秘钥
    :return:{bytes}加密后的数据
    """
    assert type(key) is str
    k = bytes(key,"utf8")
    klen= len(k)
    kindex = 0
    fileData = bytearray(fileData)
    for i,v in enumerate(fileData):
        if kindex >= klen:
            kindex = 0
        fileData[i] = v ^ k[kindex]#加密
        kindex = kindex + 1
    return bytes(_ENCRYSIG,"utf8") + fileData
 
#处理图片
def processPNG(filePath):
    global filenum
    fileData = None
    with open(filePath,'rb') as file:
        fileData = encryption(preProcessPng(file.read()),_KEY)
    os.remove(filePath)
    with open(filePath,'wb') as file: #覆盖新文件
        file.write(fileData)
    filenum = filenum + 1
 
 
 
def traverseDir(absDir):#遍历当前目录以及递归的子目录,找到所有的png图片
    """
    :param absDir: 要遍历的路径
    :return: None
    """
    assert (os.path.isdir(absDir) and os.path.isabs(absDir))
    dirName = absDir
    for fileName in os.listdir(absDir):
        absFileName = os.path.join(dirName,fileName)
        print("isPNG:",absFileName)
        if os.path.isdir(absFileName):#递归查找文件夹
            print("absFileName:",absFileName)
            traverseDir(absFileName)
        elif isPNG(absFileName):
            print("isPNG:",absFileName)
            processPNG(absFileName)
        else:
            pass
 
 
 #------------------- 主函数-------------------------#
start_clock = time.clock()
filenum = 0
#traverseDir(os.path.join(CUR_DIR,"png2"))
traverseDir(CUR_DIR)
end_clock = time.clock()
time = (end_clock - start_clock)*1000
print("encrypt %d Png Pictures"%filenum)
print("use time %fms"%time)

解密的cpp文件

1.新增图片类型

enum class Format
{
    //! JPEG
    JPG,
    //! PNG
    PNG,
    //! ENCRYPTEDPNG,下面这行是新加的
    ENCRYPTEDPNG, //加密后的Png图片
    //! TIFF
    TIFF,
    //! WebP
    WEBP,
    //! PVR
    PVR,
    //! ETC
    ETC,
    //! S3TC
    S3TC,
    //! ATITC
//    ATITC,
    //! TGA
    TGA,
    //! Raw Data
    RAW_DATA,
    //! Unknown format
    UNKNOWN
};

2.新增Image::isEncryptedPng方法:

bool Image::isEncryptedPng(const unsigned char *data, ssize_t dataLen)
{
    if (dataLen <= 7 || memcmp("jiaozhi", data, 7) != 0) {
        return false;
    }
    return true;
}

3.修改检测图片类型的Image::detectFormat方法:

Image::Format Image::detectFormat(const unsigned char * data, ssize_t dataLen)
{
    if (isPng(data, dataLen))
    {
        return Format::PNG;
    }
    //新增判断
    else if (isEncryptedPng(data, dataLen)) {
        return Format::ENCRYPTEDPNG;
    }
    else if (isJpg(data, dataLen))
    {
        return Format::JPG;
    }
    else if (isTiff(data, dataLen))
    {
        return Format::TIFF;
    }
    else if (isWebp(data, dataLen))
    {
        return Format::WEBP;
    }
    else if (isPvr(data, dataLen))
    {
        return Format::PVR;
    }
    else if (isEtc(data, dataLen))
    {
        return Format::ETC;
    }
    else if (isS3TC(data, dataLen))
    {
        return Format::S3TC;
    }
    else
    {
        return Format::UNKNOWN;
    }
}

4.修改Image::initWithImageData,进行解密png

bool Image::initWithImageData(const unsigned char * data, ssize_t dataLen)
{
    bool ret = false;
 
    do
    {
        CC_BREAK_IF(! data || dataLen <= 0);
 
        unsigned char* unpackedData = nullptr;
        ssize_t unpackedLen = 0;
 
        //detect and unzip the compress file
        if (ZipUtils::isCCZBuffer(data, dataLen))
        {
            unpackedLen = ZipUtils::inflateCCZBuffer(data, dataLen, &unpackedData);
        }
        else if (ZipUtils::isGZipBuffer(data, dataLen))
        {
            unpackedLen = ZipUtils::inflateMemory(const_cast<unsigned char*>(data), dataLen, &unpackedData);
        }
        else
        {
            unpackedData = const_cast<unsigned char*>(data);
            unpackedLen = dataLen;
        }
 
        _fileType = detectFormat(unpackedData, unpackedLen);
 
        switch (_fileType)
        {
            //这个case块是增加的内容
            case Format::ENCRYPTEDPNG:
            {
                unsigned char* copyData = new unsigned char[unpackedLen + 13]; // 8 + 12 - 7
                memcpy(copyData + 8, unpackedData + 7, unpackedLen - 7);
                deEncryptPng(&copyData, "jiaozi2013", unpackedLen + 13);
                ret = initWithPngData(copyData, unpackedLen + 13);
                delete [] copyData;
            }
            break;
        case Format::PNG:
            ret = initWithPngData(unpackedData, unpackedLen);
            break;
        case Format::JPG:
            ret = initWithJpgData(unpackedData, unpackedLen);
            break;
        case Format::TIFF:
            ret = initWithTiffData(unpackedData, unpackedLen);
            break;
        case Format::WEBP:
            ret = initWithWebpData(unpackedData, unpackedLen);
            break;
        case Format::PVR:
            ret = initWithPVRData(unpackedData, unpackedLen);
            break;
        case Format::ETC:
            ret = initWithETCData(unpackedData, unpackedLen);
            break;
        case Format::S3TC:
            ret = initWithS3TCData(unpackedData, unpackedLen);
            break;
        default:
            {
                // load and detect image format
                tImageTGA* tgaData = tgaLoadBuffer(unpackedData, unpackedLen);
 
                if (tgaData != nullptr && tgaData->status == TGA_OK)
                {
                    ret = initWithTGAData(tgaData);
                }
                else
                {
                    CCLOG("Image: unsupported image format!");
                }
 
                free(tgaData);
                break;
            }
        }
 
        if(unpackedData != data)
        {
            free(unpackedData);
        }
    } while (0);
 
    return ret;
}

5.新增Image::deEncryptPng做解密:

void Image::deEncryptPng(unsigned char **copyData, const char *key, ssize_t dataLen) {
    static const unsigned char PNG_SIGNATURE[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a };
    static const unsigned char PNG_IEND[] = { 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82 };
    unsigned char* data = *copyData;
    memcpy(data, PNG_SIGNATURE, 8);
    memcpy(data + (dataLen - 12), PNG_IEND, 12);
    unsigned char* destart = data + 8;
    unsigned char* de_end = data + dataLen - 13;
    ssize_t keyLen = strlen(key);
    ssize_t keyIndex = 0;
    for(; destart <= de_end; destart++, keyIndex++) {
        if (keyIndex >= keyLen)
            keyIndex = 0;
        *destart ^= key[keyIndex];
    }
}

最后加一句:python大法好。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
A:在cocos2dx中,可以通过加密lua代码和图片资源来保护项目的安全性。下面是一些简单的步骤来加密和解密lua代码和图片资源: 1. 加密Lua代码 可以使用luajit来编译Lua代码,然后使用gzip压缩和base64编码来加密Lua代码。以下是使用此方法加密Lua代码的示例代码: ``` local status, bytecodes = pcall(function() local bytecodeStream = io.popen("luajit -bg myScript.lua -") local bytecode = bytecodeStream:read("*all") bytecodeStream:close() return bytecode end) if not status then error(bytecodes) end local compressed = zlib.compress(bytecodes, 9) local cipher = mime.b64(compressed) ``` 2. 加密图片资源 可以使用图片加密工具,如TexturePacker,将图片打包成一个txp包。然后可以使用AES加密算法来加密txp包,以下是使用此方法加密图片资源的示例代码: ``` local Crypto = require "crypto" local data = cc.FileUtils:getInstance():getDataFromFile("myImage.txp") local iv = Crypto.digest("sha256", "mySecretKey", true) local key = Crypto.digest("md5", "mySecretKey", true) local encrypted = Crypto.encryptAES256(data, key, iv) cc.FileUtils:getInstance():writeDataToFile(encrypted, "myImageEncrypted") ``` 3. 解密Lua代码 可以使用base64解码和gzip解压缩函数解密加密的Lua代码,然后使用loadstring函数来运行解密后的代码。以下是使用此方法解密Lua代码的示例代码: ``` local cipher = "..." local compressed = mime.unb64(cipher) local bytecodes = zlib.decompress(compressed) local f = loadstring(bytecodes) f() ``` 4. 解密图片资源 使用AES解密算法来解密加密图片资源。以下是使用此方法解密图片资源的示例代码: ``` local Crypto = require "crypto" local encrypted = cc.FileUtils:getInstance():getDataFromFile("myImageEncrypted") local iv = Crypto.digest("sha256", "mySecretKey", true) local key = Crypto.digest("md5", "mySecretKey", true) local decrypted = Crypto.decryptAES256(encrypted, key, iv) cc.FileUtils:getInstance():writeDataToFile(decrypted, "myImage") ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值