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

1. 如何对图片加密

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

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.

1

2

3

读取加密后的图片

暂时没有想到更好的办法,只好修改了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 <= 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

{

// 注释掉这个分支其余代码,如果图片数据data为加密的,必须首先解密才可正常使用

// unpackedData = const_cast<unsigned char*>(data);

// unpackedLen = dataLen;

// 加密key

const unsigned char* key = "encrypt_key_sample";

int key_len = 18;

// 加密sign

const unsigned char* sign = "encrypt_sign_sample";

int sign_len = 19;

xxtea_long len = 0;

// 如果加密的数据最开始几个字节如果与签名相符,则是加密的数据

if (strncmp((const char*)data, sign, sign_len == 0) {

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;

}

... // 后面代码无需更改

}

}


这样就可以了。