天天看點

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;
            }
            ... // 後面代碼無需更改
        }
}
           

這樣就可以了。