使用 TexturePacker 進行資源加密

導出 pvr 格式

TexturePacker 可以導出的圖片格式有很多種,除了常見的 png,jpg,bmp,ttif,tga 之外,還可以導出 pvr,pvr+gzip(pvr.gz),pvr+zlib(pvr.ccz)。pvr 是 ios 上常用的一種圖片格式,iOS 設備用的是 PowerVR 顯示芯片,而 PVR 格式可以被該顯示芯片直接存取,從而速度更快。使用一般的圖片查看工具是無法打開 pvr 文件的,因此將資源導出爲 pvr 格式可達到一定的加密程序。
在 cocos2d-x 中加載 pvr 格式圖片與加載 png 圖片一樣,使用 SpriteFrameCache 加載合圖

cc.SpriteFrameCache:getInstance():addSpriteFrames(fileName .. ".plist", fileName .. ".pvr.ccz")

一個要注意的問題的是 cocostudio 也有一個導出合圖的工具,它的功能比較簡單,只能導出 png 這種常規圖片,因此如果要導出 pvr 圖片或利用其它強大的功能,則需要使用 TexturePacker。但 TexturePacker 與 cocostudio 導出的文件略有不同,一個明顯的區別就是每一幀的命名方式,cocostudio 會加上目錄,而 TexturePacker 不會。舉個例子,在 ui 目錄下有 p1.png,p2.png,p3.png 三張圖片,使用 cocostudio 打包後每一幀的文件名分別是 ui/p1.png,ui/p2.png,ui/p3.png;而使用 TexturePacker 打包後的每一幀文件名是 p1.png,p2.png,p3.png,所以從精靈幀緩衝區獲取精靈幀的方式也不同

-- 使用 cocostudio 打包圖片
cc.SpriteFrameCache:getInstance():getSpriteFrameByName("ui/" .. fileName .. ".png")
-- 使用 TexturePacker 打包圖片
cc.SpriteFrameCache:getInstance():getSpriteFrameByName(fileName .. ".png")

對 pvr 圖片進行加密

雖然使用一般的圖片查看工具無法打開 pvr 圖片,但還是會有很多特別的工具可以查看甚至轉換 pvr 圖片,最簡單好用的就是使用 TexturePacker。TexturePacker 有個 PVR Viewer 工具,可以直接打開 pvr 格式的圖片進行查看,還可以將 pvr 文件轉換成 png 圖片。別人甚至不需要查看或轉換 pvr 圖片,直接在代碼里加載也行。因此,把資源打包成 pvr 格式也並不安全,只是給別人破解增加了一點點難度而已,並不能做到真正的加密。幸運的是,TexturePacker 又給我們提供了一種加密的方式;這種加密只適用於 pvr.ccz 格式的圖片,因此導出圖片格式必須選擇 pvr.ccz。

TP加密

首先,點擊 Content protection 右邊的這個鎖,會彈出一個操作框
* Create new key 就是隨機生成一個 key
* Clear/Diable 就是取消 key,不加密
* Save as global key 就是把當前生成的 key 保存爲全局密鑰
* Use global key 就是使用全局密鑰來加密

我們點擊 Create new key 或者 Use global key,可以看到上面的文本框裏出現了一個 128 位的密鑰;點擊 close 關閉操作框,然後點擊 Publish sprite sheet 重新發布資源,這時候就生成了一個加密後的 pvr 圖片。使用 PVR Viewer 打開剛生成的 pvr 文件

打開prv圖片

可以看到它要求我們輸入密鑰後才能查看,輸入我們加密時使用的密鑰就可以正常查看和轉換 pvr 圖片了;而別人不知道我們的密鑰,所以想破解我們的資源就很困難了。
如果使用腳本命令來打包圖片的話,則加上參數 --content-protection <key> 就可以實現加密。

在 cocos2d-x 中加載加密後的資源

加密後的 pvr 文件如果不經處理直接在 cocos2d-x 中加載是加載不了的,這樣別人即使拿到我們的資源也無法在代碼中直接使用。資源加密後雖然別人無法直接使用我們的資源,但我們自己也同樣無法直接使用,因此要使用加密時的密鑰進行解密。使用 ZipUtils 進行解密,cocos2dx 中有 ZipUtils.h 和 ZipUtils.cpp 這兩個文件,不同版本的引擎所在目錄可能不同,我使用的是 cocos2d-x3.10,這兩個文件在 %COCOS_ROOT%\cocos\base 下。要在第一次加載資源之前調用解決算法,關於如何在 cocos2d-x 中使用 ZipUtils 解決資源,可以參考下面這篇文章
https://www.codeandweb.com/texturepacker/contentprotection
根據這篇文章介紹,我們要找到 cocos2d-x 的 ZipUtils.h 和 ZipUtils.cpp 這兩個文件,然後使用這篇文章的提供的文件替換這兩個文件的內容,然後調用 caw_setkey_part 這個函數四次,假如我們的密鑰是 0xaaaaaaaabbbbbbbbccccccccdddddddd

caw_setkey_part(0, 0xaaaaaaaa);
caw_setkey_part(1, 0xbbbbbbbb);
caw_setkey_part(2, 0xcccccccc);
caw_setkey_part(3, 0xdddddddd);

這種做法雖然可行,但這是針對老版本 cocos2d 的做法,新版本的 cocos2d-x 有更簡單的方法。在 cocos2d-x3.x 中,不需要替換 ZipUtils.h 和 ZipUtils.cpp 的內容,也不使用 caw_setkey_part 函數,而是使用

ZipUtils::setPvrEncryptionKey(0xaaaaaaaa, 0xbbbbbbbb, 0xcccccccc, 0xdddddddd);

查看 setPvrEncryptionKey 的源碼實現

void ZipUtils::setPvrEncryptionKey(unsigned int keyPart1, unsigned int keyPart2, unsigned int keyPart3, unsigned int keyPart4)
{
    setPvrEncryptionKeyPart(0, keyPart1);
    setPvrEncryptionKeyPart(1, keyPart2);
    setPvrEncryptionKeyPart(2, keyPart3);
    setPvrEncryptionKeyPart(3, keyPart4);
}

其實是調用了四次 setPvrEncryptionKeyPart 函數,setPvrEncryptionKeyPart 的作用與 caw_setkey_part 一樣。因此,在 cocos2d-x3.x 中解密 pvr 圖片很簡單,只需要在第一次加載 pvr 資源之前調用一次 setPvrEncryptionKey 函數即可。可以在 AppDelegate 的 applicationDidFinishLaunching 中調用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章