您的位置:首页 > 移动开发 > Cocos引擎

cocos2dx-lua 3.4 之 图片资源加密!

2017-01-11 16:21 477 查看

一、前言

1.我将要给大家分享的是XXTEA加密方式,对图片资源进行加密。

2.需要工具:quick-lua中已经集成图片加密工具,但是我没有用quick,所以单独把这个加密文件夹拎出来了。点击下载加密工具
http://pan.baidu.com/s/1pLyI6NL

二、修改CCFileUtils.h和cpp文件

1.找到frameworks\cocos2d-x\cocos\platform\CCFileUtils.h,添加一个结构体ResEncryptData:
class CC_DLL FileUtils
{
public:
//=====添加代码
static struct ResEncryptData{
ResEncryptData(){
allowNoEncrpt = true;
key = "key123456";
sign = "sign520";
}
std::string key;
std::string sign;
bool allowNoEncrpt;
}encryptData;
static unsigned char* decryptBuffer(unsigned char* buf, unsigned long size, unsigned long *newSize);
//=====添加结束
/**
*  Gets the instance of FileUtils.
*/
static FileUtils* getInstance();

/**
*  Destroys the instance of FileUtils.
*/
static void destroyInstance();
2.找到frameworks\cocos2d-x\cocos\platform\CCFileUtils.cpp,添加对应的实现代码:
//头文件声明=====
#include "xxtea/xxtea.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
#include "xxtea/xxtea.cpp"
#endif

unsigned char* FileUtils::decryptBuffer(unsigned char* buf, unsigned long size, unsigned long *newSize){
unsigned char *m_xxteaKey = (unsigned char *)FileUtils::encryptData.key.c_str();
unsigned char *m_xxteaSign = (unsigned char *)FileUtils::encryptData.sign.c_str();
xxtea_long m_xxteaSignLen = FileUtils::encryptData.sign.length();
xxtea_long m_xxteaKeyLen = FileUtils::encryptData.key.length();

if (NULL==buf) return NULL;

unsigned char* buffer = NULL;

bool isXXTEA = true;
for (unsigned int i = 0; isXXTEA && i < m_xxteaSignLen && i < size; ++i)
{
if(buf[i] != m_xxteaSign[i]){
isXXTEA = false;
break;
}
}
if(m_xxteaSignLen == 0){
isXXTEA = false;
}

if (isXXTEA)
{
// decrypt XXTEA
xxtea_long len = 0;
buffer = xxtea_decrypt(buf + m_xxteaSignLen,
(xxtea_long)size - (xxtea_long)m_xxteaSignLen,
(unsigned char*)m_xxteaKey,
(xxtea_long)m_xxteaKeyLen,
&len);
delete []buf;
buf = NULL;
size = len;
}
else
{
if(FileUtils::getInstance()->encryptData.allowNoEncrpt)
{buffer = buf;}
}

*newSize = size;
return buffer;
}


3.在上面那个文件中:frameworks\cocos2d-x\cocos\platform\CCFileUtils.cpp,修改getData函数:
static Data getData(const std::string& filename, bool forString)
{
if (filename.empty())
{
return Data::Null;
}

Data ret;
unsigned char* buffer = nullptr;
size_t size = 0;
size_t readsize;
const char* mode = nullptr;

if (forString)
mode = "rt";
else
mode = "rb";

do
{
// Read the file from hardware
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filename);
FILE *fp = fopen(fullPath.c_str(), mode);
CC_BREAK_IF(!fp);
fseek(fp,0,SEEK_END);
size = ftell(fp);
fseek(fp,0,SEEK_SET);

if (forString)
{
buffer = (unsigned char*)malloc(sizeof(unsigned char) * (size + 1));
buffer[size] = '\0';
}
else
{
buffer = (unsigned char*)malloc(sizeof(unsigned char) * size);
}

readsize = fread(buffer, sizeof(unsigned char), size, fp);
fclose(fp);

if (forString && readsize < size)
{
buffer[readsize] = '\0';
}
} while (0);

if (nullptr == buffer || 0 == readsize)
{
std::string msg = "Get data from file(";
msg.append(filename).append(") failed!");
CCLOG("%s", msg.c_str());
}
else
{
//ret.fastSet(buffer, readsize);
//======新的改动
unsigned long newSize = 0;
unsigned char *newBuffer = FileUtils::decryptBuffer(buffer, readsize, &newSize);
ret.fastSet(newBuffer, newSize);
}


4.在上面那个文件中:frameworks\cocos2d-x\cocos\platform\CCFileUtils.cpp,修改getFileData函数:

unsigned char* FileUtils::getFileData(const std::string& filename, const char* mode, ssize_t *size)
{
unsigned char * buffer = nullptr;
CCASSERT(!filename.empty() && size != nullptr && mode != nullptr, "Invalid parameters.");
*size = 0;
do
{
// read the file from hardware
const std::string fullPath = fullPathForFilename(filename);
FILE *fp = fopen(fullPath.c_str(), mode);
CC_BREAK_IF(!fp);

fseek(fp,0,SEEK_END);
*size = ftell(fp);
fseek(fp,0,SEEK_SET);
buffer = (unsigned char*)malloc(*size);
*size = fread(buffer,sizeof(unsigned char), *size,fp);
fclose(fp);
} while (0);

if (!buffer)
{
std::string msg = "Get data from file(";
msg.append(filename).append(") failed!");

CCLOG("%s", msg.c_str());
}else{
//新的改动=========
unsigned long newSize = 0;
unsigned char *newBuffer = FileUtils::decryptBuffer(buffer, *size, &newSize);
*size = newSize;
buffer = newBuffer;
}
return buffer;
}

三、修改CCFileUtils-win32.cpp文件

1.找到frameworks\cocos2d-x\cocos\platform\win32\CCFileUtils-win32.cpp,添加对应的代码:

static Data getData(const std::string& filename, bool forString)
{
if (filename.empty())
{
return Data::Null;
}

unsigned char *buffer = nullptr;

size_t size = 0;
do
{
// read the file from hardware
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filename);

WCHAR wszBuf[CC_MAX_PATH] = {0};
MultiByteToWideChar(CP_UTF8, 0, fullPath.c_str(), -1, wszBuf, sizeof(wszBuf)/sizeof(wszBuf[0]));

HANDLE fileHandle = ::CreateFileW(wszBuf, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, nullptr);
CC_BREAK_IF(fileHandle == INVALID_HANDLE_VALUE);

size = ::GetFileSize(fileHandle, nullptr);

if (forString)
{
buffer = (unsigned char*) malloc(size + 1);
buffer[size] = '\0';
}
else
{
buffer = (unsigned char*) malloc(size);
}
DWORD sizeRead = 0;
BOOL successed = FALSE;
successed = ::ReadFile(fileHandle, buffer, size, &sizeRead, nullptr);
::CloseHandle(fileHandle);

if (!successed)
{
// should determine buffer value, or it will cause memory leak
if (buffer)
{
free(buffer);
buffer = nullptr;
}
}
} while (0);

Data ret;

if (buffer == nullptr || size == 0)
{
std::string msg = "Get data from file(";
// Gets error code.
DWORD errorCode = ::GetLastError();
char errorCodeBuffer[20] = {0};
snprintf(errorCodeBuffer, sizeof(errorCodeBuffer), "%d", errorCode);

msg = msg + filename + ") failed, error code is " + errorCodeBuffer;
CCLOG("%s", msg.c_str());

if (buffer)
free(buffer);
}
else
{
//新的改动
unsigned long newSize = 0;
unsigned char *newBuffer = FileUtils::decryptBuffer(buffer, size, &newSize);
//ret.fastSet(buffer, size);
ret.fastSet(newBuffer, newSize);
}
return ret;
}

unsigned char* FileUtilsWin32::getFileData(const std::string& filename, const char* mode, ssize_t* size)
{
unsigned char * pBuffer = nullptr;
*size = 0;
do
{
// read the file from hardware
std::string fullPath = fullPathForFilename(filename);

WCHAR wszBuf[CC_MAX_PATH] = {0};
MultiByteToWideChar(CP_UTF8, 0, fullPath.c_str(), -1, wszBuf, sizeof(wszBuf)/sizeof(wszBuf[0]));

HANDLE fileHandle = ::CreateFileW(wszBuf, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, nullptr);
CC_BREAK_IF(fileHandle == INVALID_HANDLE_VALUE);

*size = ::GetFileSize(fileHandle, nullptr);

pBuffer = (unsigned char*) malloc(*size);
DWORD sizeRead = 0;
BOOL successed = FALSE;
successed = ::ReadFile(fileHandle, pBuffer, *size, &sizeRead, nullptr);
::CloseHandle(fileHandle);

if (!successed)
{
free(pBuffer);
pBuffer = nullptr;
}
} while (0);

if (! pBuffer)
{
std::string msg = "Get data from file(";
// Gets error code.
DWORD errorCode = ::GetLastError();
char errorCodeBuffer[20] = {0};
snprintf(errorCodeBuffer, sizeof(errorCodeBuffer), "%d", errorCode);

msg = msg + filename + ") failed, error code is " + errorCodeBuffer;
CCLOG("%s", msg.c_str());
}else{
//新的改动
unsigned long newSize = 0;
unsigned char *newBuffer = FileUtils::decryptBuffer(pBuffer, *size, &newSize);
*size = newSize;
pBuffer = newBuffer;
}
return pBuffer;
}

四、修改CCFileUtils-android.cpp文件

1.找到frameworks\cocos2d-x\cocos\platform\android\CCFileUtils-android.cpp,添加对应的代码:

Data FileUtilsAndroid::getData(const std::string& filename, bool forString)
{
if (filename.empty())
{
return Data::Null;
}

unsigned char* data = nullptr;
ssize_t size = 0;
string fullPath = fullPathForFilename(filename);
cocosplay::updateAssets(fullPath);

if (fullPath[0] != '/')
{
string relativePath = string();

size_t position = fullPath.find("assets/");
if (0 == position) {
// "assets/" is at the beginning of the path and we don't want it
relativePath += fullPath.substr(strlen("assets/"));
} else {
relativePath += fullPath;
}
CCLOGINFO("relative path = %s", relativePath.c_str());

if (nullptr == FileUtilsAndroid::assetmanager) {
LOGD("... FileUtilsAndroid::assetmanager is nullptr");
return Data::Null;
}

// read asset data
AAsset* asset =
AAssetManager_open(FileUtilsAndroid::assetmanager,
relativePath.c_str(),
AASSET_MODE_UNKNOWN);
if (nullptr == asset) {
LOGD("asset is nullptr");
return Data::Null;
}

off_t fileSize = AAsset_getLength(asset);

if (forString)
{
data = (unsigned char*) malloc(fileSize + 1);
data[fileSize] = '\0';
}
else
{
data = (unsigned char*) malloc(fileSize);
}

int bytesread = AAsset_read(asset, (void*)data, fileSize);
size = bytesread;

AAsset_close(asset);
}
else
{
do
{
// read rrom other path than user set it
//CCLOG("GETTING FILE ABSOLUTE DATA: %s", filename);
const char* mode = nullptr;
if (forString)
mode = "rt";
else
mode = "rb";

FILE *fp = fopen(fullPath.c_str(), mode);
CC_BREAK_IF(!fp);

long fileSize;
fseek(fp,0,SEEK_END);
fileSize = ftell(fp);
fseek(fp,0,SEEK_SET);
if (forString)
{
data = (unsigned char*) malloc(fileSize + 1);
data[fileSize] = '\0';
}
else
{
data = (unsigned char*) malloc(fileSize);
}
fileSize = fread(data,sizeof(unsigned char), fileSize,fp);
fclose(fp);

size = fileSize;
} while (0);
}

Data ret;
if (data == nullptr || size == 0)
{
std::string msg = "Get data from file(";
msg.append(filename).append(") failed!");
CCLOG("%s", msg.c_str());
}
else
{
//新的改动==========
unsigned long newSize = 0;
unsigned char *newBuffer = FileUtils::decryptBuffer(data, size, &newSize);
// ret.fastSet(data, size);
ret.fastSet(newBuffer, newSize);
cocosplay::notifyFileLoaded(fullPath);
}

return ret;
}

unsigned char* FileUtilsAndroid::getFileData(const std::string& filename, const char* mode, ssize_t * size)
{
unsigned char * data = 0;

if ( filename.empty() || (! mode) )
{
return 0;
}

string fullPath = fullPathForFilename(filename);
cocosplay::updateAssets(fullPath);

if (fullPath[0] != '/')
{
string relativePath = string();

size_t position = fullPath.find("assets/");
if (0 == position) {
// "assets/" is at the beginning of the path and we don't want it
relativePath += fullPath.substr(strlen("assets/"));
} else {
relativePath += fullPath;
}
LOGD("relative path = %s", relativePath.c_str());

if (nullptr == FileUtilsAndroid::assetmanager) {
LOGD("... FileUtilsAndroid::assetmanager is nullptr");
return nullptr;
}

// read asset data
AAsset* asset =
AAssetManager_open(FileUtilsAndroid::assetmanager,
relativePath.c_str(),
AASSET_MODE_UNKNOWN);
if (nullptr == asset) {
LOGD("asset is nullptr");
return nullptr;
}

off_t fileSize = AAsset_getLength(asset);

data = (unsigned char*) malloc(fileSize);

int bytesread = AAsset_read(asset, (void*)data, fileSize);
if (size)
{
*size = bytesread;
}

AAsset_close(asset);
}
else
{
do
{
// read rrom other path than user set it
//CCLOG("GETTING FILE ABSOLUTE DATA: %s", filename);
FILE *fp = fopen(fullPath.c_str(), mode);
CC_BREAK_IF(!fp);

long fileSize;
fseek(fp,0,SEEK_END);
fileSize = ftell(fp);
fseek(fp,0,SEEK_SET);
data = (unsigned char*) malloc(fileSize);
fileSize = fread(data,sizeof(unsigned char), fileSize,fp);
fclose(fp);

if (size)
{
*size = fileSize;
}
} while (0);
}

if (! data)
{
std::string msg = "Get data from file(";
msg.append(filename).append(") failed!");
CCLOG("%s", msg.c_str());
}
else
{
//新的改动
unsigned long newSize = 0;
unsigned char *newBuffer = FileUtils::decryptBuffer(data, *size, &newSize);
*size = newSize;
data = newBuffer;

cocosplay::notifyFileLoaded(fullPath);
}

return data;
}

五、修改CCFileUtils-apple.mm文件

1.找到frameworks\cocos2d-x\cocos\platform\apple\CCFileUtils-apple.cpp,修改对应的代码:getValueMapFromFile。以便读取plist文件,是因为ios读取plist文件方式和android和win32不同。

ValueMap FileUtilsApple::getValueMapFromFile(const std::string& filename)
{
//====新的改动
std::string fullPath = fullPathForFilename(filename);
Data d = FileUtils::getDataFromFile(filename);
unsigned long fileSize = d.getSize();
unsigned char* pFileData = d.getBytes();
NSData *data = [[[NSData alloc] initWithBytes:pFileData length:fileSize] autorelease];
NSPropertyListFormat format;
NSString *error;
NSMutableDictionary *dict = (NSMutableDictionary *)[
NSPropertyListSerialization propertyListFromData:data
mutabilityOption:NSPropertyListMutableContainersAndLeaves
format:&format
errorDescription:&error];
//====改动结束

//std::string fullPath = fullPathForFilename(filename);
//NSString* path = [NSString stringWithUTF8String:fullPath.c_str()];
//NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile:path];

ValueMap ret;

if (dict != nil)
{
for (id key in [dict allKeys])
{
id value = [dict objectForKey:key];
addValueToDict(key, value, ret);
}
}
return ret;
}


六、大功告成!

1.重新编译c++代码,把res文件夹替换成加密后的文件夹,即可正常运行。
2.注意key和sign要和你的AppDelegate中设置的key和sign一样:
LuaStack* stack = LuaEngine::getInstance()->getLuaStack();
stack->setXXTEAKeyAndSign(key, strlen(key), sign, strlen(sign));
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐