quick-x 图片资源加密



本文源自:http://my.oschina.net/SunLightJuly/blog/184061



quick-x已经支持用XXTEA加密方式对脚本文件进行加密。在此基础上,自己做了一些工作,对图片资源进行了XXTEA加密,现分享给大家。

(2014.5.30加注:quick-x的2.2.3版本已经集成了我递交的pr,现在官方版本代码与文章中类似)

首先我们要有对图片加密的工具。这个参考compile_scripts脚本,写一个用于加密的脚本就可以了。我自己写的脚本放在这里,大家可以下载使用。(之前没用过php,完全是照着廖大的脚本修改成的,有写得不好的地方还请多多包涵,呵呵)

脚本使用的方法和compile_scripts脚本差不多,将zip包里的文件解压到quick-x的bin目录下就可以用了。

在Windows命令行下,输入以下指令(请确认环境变量PATH里有quick-x的bin目录,否则需要自己加运行路径)

?
1
pack_files.bat -i olddir -o newdir -ek XXTEA -es tsts

以上指令是将olddir目录下的所有文件用XXTEA加密后,放到newdir目录下,其中加密密匙为XXTEA,加密记号为tsts。参数的定义与compile_scripts脚本类似,用-h也可以得到帮助,也不多说了。

MAC下可以用pack_files.sh来加密。

需要注意的是,现在只支持图片的加密。比如AllSprites.plist和AllSprites.png这样的一对纹理文件,只能加密png文件,plist文件加密后是用不了的。(注:现在已经支持plist文件,请看“后篇”里的内容)

文件加密好以后,我们需要修改quick-x的平台代码,使得它能够读取加密后的文件。

载入图片的函数是lib\cocos2d-x\cocos2dx\platform\CCImageCommon_cpp.h里面的CCImage::initWithImageFile()和CCImage::initWithImageFileThreadSafe()。再进一步看,这两个函数里都是使用CCFileUtils::sharedFileUtils()->getFileData()来获得文件数据的,我们只需要在获取数据时把文件数据解密即可。

为此我们需要专门写一个新的getFileData()来代替调用。直接写一个是可以的,放在哪个文件里也不重要。因为我自己有一个HelperFunc模块,专门放自己增加的功能的,所以我就写在这里面了。文件里的相关代码如下:

HelperFunc.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifndef Cocos2Dx_HelperFunc_h
#define Cocos2Dx_HelperFunc_h
 
NS_CC_BEGIN
 
class CZHelperFunc
{
public :
     static unsigned char * getFileData( const char * pszFileName, const char * pszMode, unsigned long * pSize);
 
};
 
NS_CC_END
 
#endif //Cocos2Dx_HelperFunc_h

HelperFunc.cpp

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include "cocos2d.h"
extern "C" {
#include "lua.h"
#include "xxtea.h"
}
#include "CCLuaEngine.h"
#include "HelperFunc.h"
 
USING_NS_CC;
 
unsigned char * CZHelperFunc::getFileData( const char * pszFileName, const char * pszMode, unsigned long * pSize)
{
   unsigned long size;
   unsigned char * buf = CCFileUtils::sharedFileUtils()->getFileData(pszFileName, pszMode, &size);
   if (NULL==buf) return NULL;
 
   CCLuaStack* stack = CCLuaEngine::defaultEngine()->getLuaStack();
   unsigned char * buffer = NULL;
 
     bool isXXTEA = stack && stack->m_xxteaEnabled;
     for (unsigned int i = 0 ; isXXTEA && i < stack->m_xxteaSignLen && i < size; ++i)
     {
         isXXTEA = buf[i] == stack->m_xxteaSign[i];
     }
 
     if (isXXTEA)
     {
         // decrypt XXTEA
         xxtea_long len = 0 ;
         buffer = xxtea_decrypt(buf + stack->m_xxteaSignLen,
                                (xxtea_long)size - (xxtea_long)stack->m_xxteaSignLen,
                                (unsigned char *)stack->m_xxteaKey,
                                (xxtea_long)stack->m_xxteaKeyLen,
                                &len);
         delete []buf;
         buf = NULL;
         size = len;
     }
     else
     {
         buffer = buf;
     }
 
     if (pSize) *pSize = size;
     return buffer;
}

因为上面代码里直接使用了CCLuaStack里的密匙等数据,所以要修改一下lib\cocos2d-x\scripting\lua\cocos2dx_support\CCLuaStack.h,把里面的几个属性改成公有的才能调用。当然我这是偷懒了,安全的做法应该是加几个取值的方法,呵呵。

?
1
2
3
4
5
6
public :
   bool  m_xxteaEnabled;
   char *m_xxteaKey;
   int   m_xxteaKeyLen;
   char *m_xxteaSign;
   int   m_xxteaSignLen;

另外,我们需要在程序启动时设置一下密匙和标记,这就要修改AppDelegate.cpp里的AppDelegate::applicationDidFinishLaunching(),在下面这句:

?
1
CCLuaStack *pStack = pEngine->getLuaStack();

这句后面加上:

?
1
pStack->setXXTEAKeyAndSign( "XXTEA" , strlen( "XXTEA" ), "tsts" , strlen( "tsts" ));

注意最新版本的quick-x里,player的AppDelegate.cpp修改的地方是StartupCall::startup()函数。

现在把CCImageCommon_cpp.h里的CCFileUtils::sharedFileUtils()->getFileData改为CZHelperFunc::getFileData就可以了。当然,必须包含HelperFunc.h这个头文件才能编译通过。

(注:initWithImageFileThreadSafe函数里有一段代码是在Android平台上使用getFileDataForAsync来取文件内容,我开始这里没做修改也能在Android上正常运行,可能是因为我没使用到这一载入功能。其实这段代码可以直接去掉,都用CZHelperFunc::getFileData来处理就好。最简单的修改是将“#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)“改成”#if 0"就可以了)

经过以上修改,quick-x就能够使用加密后的图片资源了。但这只解决了Windows平台(player)和Android平台,其他的修改请看续篇。


前篇:quick-cocos2d-x图片资源加密

在前篇里面,我们实现了图片资源的加密,但还没有实现plist文件的加密。虽然这一加密不是太重要,但如果要实现也是不难的,以下是修改方法。

对plist文件的解析是在lib\cocos2d-x\cocos2dx\platform\CCSAXParser.cpp里的CCSAXParser::parse(const char *pszFile)里处理的,我们可以看到以下熟悉的语句:

1
char * pBuffer = ( char *)CCFileUtils::sharedFileUtils()->getFileData(pszFile,  "rt" , &size);

有了前篇的基础,我们只需要将这句改成以下:

1
char * pBuffer = ( char *)CZHelperFunc::getFileData(pszFile,  "rb" , &size);

注意上面的参数有所变化,"rt"改成了"rb",原因是加密后的文件不再是纯文本,所以要用b参数。

另外记得包含头文件HelperFunc.h,而且包含的语句要放在CCSAXParser.cpp文件中NS_CC_BEGIN这行语句之前,否则编译会出错。

以上修改是针对Windows平台和Android平台的,其他平台的修改请看续篇:


前篇:

quick-cocos2d-x图片资源加密

让quick-cocos2d-x支持加密的plist文件


通过前篇的修改,我们已经能够在Windows平台的player,以及Android上使用加密的常见格式(png、jpg等)的图片资源了。不过,在MAC上的player,以及IOS上,加载资源时调用的是另外的代码,所以我们需要另外作修改。

首先来修改Mac上的Player代码。我们这次要修改的是lib\cocos2d-x\cocos2dx\platform\mac目录下的CCImage.mm文件。在_initWithFile这个函数的开头,可以看到以下代码:

1
2
NSString *fullPath = [NSString stringWithUTF8String:path];
jpg = [[NSImage alloc] initWithContentsOfFile: fullPath];

我们用以下代码来代替:

1
2
3
4
5
unsigned  long  fileSize = 0;
unsigned  char * pFileData = cocos2d::CZHelperFunc::getFileData(path,  "rb" , &fileSize);
NSData *adata = [[NSData alloc] initWithBytes:pFileData length:fileSize];
delete  []pFileData;
jpg = [[NSImage alloc] initWithData:adata];

而在CCImage::initWithImageFile函数中,又看到了熟悉的语句:

1
unsigned  char * pFileData = CCFileUtils::sharedFileUtils()->getFileData(strTemp.c_str(),  "rb" , &fileSize);

修改这个应该已经很熟练了:

1
unsigned  char * pFileData = CZHelperFunc::getFileData(strTemp.c_str(),  "rb" , &fileSize);

另外,HelperFunc.h头文件的包含肯定是必须的,后面的修改也一样,就不再每次都说明了。

好,现在MAC支持加密的图片文件了。如果要支持加密的plist文件的话,还要改同一目录下的CCFileUtilsMac.mm文件。找到CCFileUtilsMac::createCCDictionaryWithContentsOfFile函数,需要修改的是这两句:

1
2
NSString* pPath = [NSString stringWithUTF8String:fullPath.c_str()];
NSDictionary* pDict = [NSDictionary dictionaryWithContentsOfFile:pPath];

需要写的代码就比以前的稍多一点了:

1
2
3
4
5
6
7
8
9
10
11
unsigned  long  fileSize = 0;
unsigned  char * pFileData = CZHelperFunc::getFileData(fullPath.c_str(),  "rb" , &fileSize);
NSData *data = [[[NSData alloc] initWithBytes:pFileData length:fileSize] autorelease];
delete  []pFileData;
NSPropertyListFormat format;
NSString *error;
NSMutableDictionary *pDict = (NSMutableDictionary *)[
                            NSPropertyListSerialization propertyListFromData:data
                            mutabilityOption:NSPropertyListMutableContainersAndLeaves
                            format:&format
                            errorDescription:&error];

改好了MAC,修改IOS就比较容易了,因为修改方法很类似,只是文件不同。要修改的是lib\cocos2d-x\cocos2dx\platform\ios目录下的CCImage.mm和CCFileUtilsIOS.mm文件。这两个文件里要修改的函数都是一样的,连需要修改的代码都几乎一样,唯一需要稍为注意的是在IOS里要用UIImage来代替Mac里的NSImage。这里就不再贴出代码了。

经过这么多修改,基本上常用的图片文件都已经支持,不过,有些特殊格式的文件也是有可能用到的,顺便提一下吧。

支持PVR文件,要修改lib\cocos2d-x\cocos2dx\textures目录下的CCTexturePVR.cpp文件,找到CCFileUtils::sharedFileUtils()->getFileData所在的那一句进行修改就是了,不需要多说了。

支持TGA文件,修改lib\cocos2d-x\cocos2dx\support\image_support下的TGAlib.cpp,类似上面,也是一条语句的事。

另外在lib\cocos2d-x\cocos2dx\textures目录下还有个文件CCTextureCache.cpp,我没细看,应该是跟TMX MAP的载入有点关系。里面也只是一条语句的事情,一起改掉吧,呵呵。

经过以上修改后,应该能满足绝大多数的加密需求了。粗粗的浏览了一下代码,应该只有PKM文件无法支持,因为它是直接通过JNI调用Android的API来对文件解码的,不是太好修改了。

以上是我个人的修改方法,肯定还有更好的改法,希望能和大家相互分享和交流。如果有错误的地方,也请大家多多指正!

(

2014.2.24更新:

支持pvr.ccz文件,需要修改lib\cocos2d-x\cocos2dx\support\zip_support\ZipUtils.cpp文件里的ccInflateCCZFile函数,也是一条读文件内容的语句,各平台下都适用。

感谢群里的朋友“蚀生”提供这一信息!

)




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值