天天看点

Cocos2d-lua 3.10 图片资源加密

在游戏发布之前,最好将图片加密,为apk/ipa加一层保护(虽然可能没用),涉及两个问题:

1. 如何对图片加密
2. 如何读取加密后的图片
           

下面详细说明。

对图片加密

Quick-3.3提供了

pack_files.sh

可以实现对图片加密,基本原理就是对每个图片使用

xxtea

加密算法对图片二进制数据进行加密,我们只需要提供密钥key和签名sign即可。具体用法如下:

# encrypt images 

./pack_files.sh -i path/to/image -o output/dir -m files -ek encrypt_key_sample -es encrypt_sign_sample
           

各个参数的意义

参数 含义
-i 待加密的图片所在目录
-o 加密后的图片输出目录
-m files,输出为单个加密后的文件
-ek 指定加密密钥
-es 指定加密签名

如果执行正常,输出类似:

Pack source files in path path/to/img
create output files in output/dir .
done.
           

读取加密后的图片

暂时没有想到更好的办法,只好修改了

CCImage.cpp

的源文件去判断图片是否加密,如果加密了,首先对其解密,再生成

CCImage

对象。

// CCImage.cpp

// 首先包含xxtea的头文件,xxtea在cocos2dx已包含,无需单独提供,只需要正确引入即可
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "xxtea.h"
#else
#include "external/xxtea/xxtea.h"
#endif

// 主要修改initWithImageData这个函数
bool Image::initWithImageData(const unsigned char * data, ssize_t dataLen)
{
    bool ret = false; 
    do
    {
        CC_BREAK_IF(! data || dataLen <= );

        unsigned char* unpackedData = nullptr;
        ssize_t unpackedLen = ;

        //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
        {
            // 注释掉这个分支其余代码,如果图片数据data为加密的,必须首先解密才可正常使用
            // unpackedData = const_cast<unsigned char*>(data);
            // unpackedLen = dataLen;

            // 加密key
            const unsigned char* key = "encrypt_key_sample";
            int key_len = ;

            // 加密sign
            const unsigned char* sign = "encrypt_sign_sample";
            int sign_len = ;

            xxtea_long len = ;
            // 如果加密的数据最开始几个字节如果与签名相符,则是加密的数据
            if (strncmp((const char*)data, sign, sign_len == ) {
                unpackedData = xxtea_decrypt((unsigned char*)data + sign_len,
                                             (xxtea_long)dataLen - sign_len,
                                             key,
                                             (xxtea_long)key_len,
                                             &len);
                unpackedLen = len;
            }
            else {
                unpackedData = const_cast<unsigned char*>(data);
                unpackedLen = dataLen;
            }
            ... // 后面代码无需更改
        }
}
           

这样就可以了。