画像リソースの暗号化、Luaファイルの暗号化
リソース保護の問題は、ゲーム開発でよく発生します。現在、ゲーム開発で暗号化されることが多いファイルタイプは、画像、Luaファイル、オーディオおよびその他のファイルですが、暗号化は両刃の剣でもあります。
セキュリティが必要な場合は、それを実装するために一定量のリソースを費やす必要があります。現在、TexturePackerツールはインターネットでの暗号化にも使用されていますが、適切性は十分ではありません。
原理を次のように分析します。
1.フォーマット変換:暗号化する必要があるファイルをストリームに変換する方法。
2.暗号化:必要に応じて、暗号化方法MD5、AESを使用し、ディスプレイスメントを直接変更します。独自の特殊文字を追加して、ファイルを簡単に暗号化します。暗号化後は、基本的に画像タイプをプレビューしたり、特殊なソフトウェアで再生したりできないことが保証されます。開くと、暗号化後にLuaファイルが文字化けします。
3.カスタムフォーマットファイルを保存します。「xx.d」、「xx.xyz」など、独自の特殊なファイル名で保存します。
4.画像の復号化:cocos2dxの基礎となるライブラリの取得パスを変更し、CCImageテクスチャ処理をロードするときにソースコードを変更します。
5.特別なLuaファイルインターフェイス:対応するLuaロード方法を変更します。
基本原則が明確になった後、私のプロジェクトで一般的に使用されているいくつかの暗号化方法について説明します。
1つ目は、フォーマットと暗号化の方法です。
bool PublicCommen :: recode_getFileByName(string pFileName){unsigned long nSize = 0;
unsigned char * pBuffer = CCFileUtils :: sharedFileUtils()-> getFileData(
pFileName.c_str()、“ rb”、&nSize);
unsigned char * newBuf = new unsigned char [nSize]; int newblen = nSize; if(pBuffer!= NULL && nSize> 0)
{for(int i = 0; i newBuf [i] = pBuffer [i] + MD5;
} string savepath = pFileName;
savepath = savepath.substr(0、savepath.length()-4);
savepath = savepath + "xx.X";
ファイル* fp = fopen(savepath.c_str()、 "wb +");
fwrite(newBuf、1、newblen、fp);
fclose(fp);
CCLOG( "save file ok。path =%s"、savepath.c_str()); trueを返します。
} falseを返します。
}
通常、カスタムディレクトリで転送する必要のあるリソースファイルをトラバースするアプリケーションを作成し、それに応じてすべてのリソースを変換および暗号化できます。newBuf[i] = pBuffer [i] + MD5内で、この段落は自由に再生できます。復号化するときに対応する必要があります!
もちろん、これをゲームで使用して、Cocos2d-xの下部にあるCCFileUtils :: fullPathForFilenameを変更して完全なパスを取得することもできます。
復号化について話しましょう:
cocos2dx CCTexture2DのCCTextureCache :: addImageクラスで、画像の復号化を変更する必要があります
CCTexture2D * CCTextureCache :: addImage(const char * path)
{
CCAssert(path!= NULL、 "TextureCache:fileimage must not NULL");
CCTexture2D *テクスチャ= NULL;
CCImage * pImage = NULL; //ディレクトリとファイル名を分割// MUTEX:// addImageAsyncが別のスレッドからこのメソッドを呼び出すために必要// pthread_mutex_lock(m_pDictLock); std :: string pathKey = path;
pathKey = CCFileUtils :: sharedFileUtils()-> fullPathForFilename(pathKey.c_str()); if(pathKey.size()== 0)
{NULLを返す;
}
テクスチャ=(CCTexture2D *)m_pTextures-> objectForKey(pathKey.c_str());
std :: string fullpath = pathKey; //(CCFileUtils :: sharedFileUtils()-> fullPathFromRelativePath(path)); if(!テクスチャ)
{
std :: string lowerCase(pathKey); for(unsigned int i = 0; i <lowerCase.length(); ++ i)
{
lowerCase [i] = tolower(lowerCase [i]);
} //独自のハンドラで処理されるPVR拡張を除くすべての画像はUIImageで処理されますdo {if(std :: string :: npos!= lowerCase.find( "。pvr"))
{
texture = this-> addPVRImage(fullpath.c_str());
} else if(std :: string :: npos!= lowerCase.find(“。pkm”))
{// ETC1ファイル形式、Androidでのみサポートされるtexture = this-> addETCImage(fullpath.c_str());
} そうしないと {
CCImage :: EImageFormat eImageFormat = CCImage :: kFmtUnKnown; if(std :: string :: npos!= lowerCase.find(“。png”))
{
eImageFormat = CCImage :: kFmtPng;
} else if(std :: string :: npos!= lowerCase.find(“。jpg”)|| std :: string :: npos!= lowerCase.find(“。jpeg”))
{
eImageFormat = CCImage :: kFmtJpg;
} else if(std :: string :: npos!= lowerCase.find(“。tif”)|| std :: string :: npos!= lowerCase.find(“。tiff”))
{
eImageFormat = CCImage :: kFmtTiff;
} else if(std :: string :: npos!= lowerCase.find(“。webp”))
{
eImageFormat = CCImage :: kFmtWebp;
} else if(std :: string :: npos!= lowerCase.find(“ XX.X”))
{
eImageFormat = CCImage :: xxxxx;
}
pImage = new CCImage();
CC_BREAK_IF(NULL == pImage); bool bRet = pImage-> initWithImageFile(fullpath.c_str()、eImageFormat);
CC_BREAK_IF(!bRet);
テクスチャ=新しいCCTexture2D(); if(texture && texture-> initWithImage(pImage))
{#if CC_ENABLE_CACHE_TEXTURE_DATA //テクスチャファイル名をキャッシュしますVolatileTexture :: addImageTexture(texture、fullpath.c_str()、eImageFormat); #endif m_pTextures-> setObject(texture、pathKey.c_str());
texture-> release();
} そうしないと {
CCLOG(“ cocos2d:ファイルのテクスチャを作成できませんでした:CCTextureCacheの%s”、パス);
}
}
}(0);
}
CC_SAFE_RELEASE(pImage); // pthread_mutex_unlock(m_pDictLock); テクスチャを返す;
}
そして、CCImage :: xxxxxのように、CCImageの画像タイプに暗号化された画像タイプを追加します。
bool bRet = pImage-> initWithImageFile(fullpath.c_str()、eImageFormat);
CCImage :: initWithImageFileメソッド(CCImage.mm内):
bool CCImage :: initWithImageFile(const char * strPath、EImageFormat eImgFmt / * = eFmtPng * /)
{bool bRet = false;
unsigned long nSize = 0;
unsigned char * pBuffer = CCFileUtils :: sharedFileUtils()-> getFileData(
CCFileUtils :: sharedFileUtils()-> fullPathForFilename(strPath).c_str()、“ rb”、&nSize); if(eImgFmt == xxxxxx)
{for(int i = 0; i <nSize; i ++){
pBuffer [i] = pBuffer [i] -MD5;
}
pBuffer [nSize] = pBuffer [nSize] -1;
eImgFmt = kFmtPng;
} if(pBuffer!= NULL && nSize> 0)
{
bRet = initWithImageData(pBuffer、nSize、eImgFmt);
}
CC_SAFE_DELETE_ARRAY(pBuffer); bRetを返す;
}
その中で、pBuffer [i] = pBuffer [i] -MD5;以前の暗号化時間に対応する必要があります。自分でプレイしてください!
OK、それが画像であり、画像がカスタムタイプに属している限り、実際のテクスチャは復号化されます。
Luaの復号化は基本的に同じアイデアですが、Luaメソッドをロードする前に復号化を個別に復号化する必要があり、クロスプラットフォームが考慮されます。