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

一、前言

1.我将要给大家分享的是XXTEA加密方式,对图片资源进行加密。
2.需要工具:quick-lua中已经集成图片加密工具,但是我没有用quick,所以单独把这个加密文件夹拎出来了。点击下载加密工具

二、修改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 *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,SEEK_END);
        size = ftell(fp);
        fseek(fp,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,SEEK_END);
        *size = ftell(fp);
        fseek(fp,SEEK_SET);
        buffer = (unsigned char*)malloc(*size);
        *size = fread(buffer,*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,&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,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,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,&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,&newSize);
        //ret.fastSet(buffer,size);
		ret.fastSet(newBuffer,newSize);
    }
    return ret;
}

unsigned char* FileUtilsWin32::getFileData(const std::string& filename,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,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,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,msg.c_str());
    }else{
		//新的改动
		unsigned long newSize = 0;
		unsigned char *newBuffer = FileUtils::decryptBuffer(pBuffer,&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,SEEK_END);
            fileSize = ftell(fp);
            fseek(fp,SEEK_SET);
            if (forString)
            {
                data = (unsigned char*) malloc(fileSize + 1);
                data[fileSize] = '\0';
            }
            else
            {
                data = (unsigned char*) malloc(fileSize);
            }
            fileSize = fread(data,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,&newSize);
        // ret.fastSet(data,newSize);
        cocosplay::notifyFileLoaded(fullPath);
    }

    return ret;
}


unsigned char* FileUtilsAndroid::getFileData(const std::string& filename,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,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,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(),SEEK_SET);
            data = (unsigned char*) malloc(fileSize);
            fileSize = fread(data,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,&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));

相关文章

    本文实践自 RayWenderlich、Ali Hafizji 的文章《...
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...