quick-cocos2d-x图片资源加密
quick-cocos2d-x图片资源加密
SunLightJuly 发表于4年前
quick-cocos2d-x图片资源加密
  • 发表于 4年前
  • 阅读 10769
  • 收藏 13
  • 点赞 1
  • 评论 28

腾讯云 十分钟定制你的第一个小程序>>>   

摘要: 在quick-cocos2d-x上实现的一种图片资源加密的方法,现已经加入官方最新版本之中

###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目录,否则需要自己加运行路径)

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

#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

#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,把里面的几个属性改成公有的才能调用。当然我这是偷懒了,安全的做法应该是加几个取值的方法,呵呵。

public:
  bool  m_xxteaEnabled;
  char *m_xxteaKey;
  int   m_xxteaKeyLen;
  char *m_xxteaSign;
  int   m_xxteaSignLen;

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

CCLuaStack *pStack = pEngine->getLuaStack();

###这句后面加上:

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文件 quick-cocos2d-x图片资源加密(续)

共有 人打赏支持
粉丝 60
博文 15
码字总数 12480
评论 (28)
渣皮人
在CCImageCommon_cpp.h里面的initWithImageFileThreadSafe()方法中,对于anroid平台,
unsigned char *pBuffer = fileUtils->getFileDataForAsync(fullpath,"rb",&Size)
需不要替换呢?
SunLightJuly

引用来自“的地方”的评论

在CCImageCommon_cpp.h里面的initWithImageFileThreadSafe()方法中,对于anroid平台,
unsigned char *pBuffer = fileUtils->getFileDataForAsync(fullpath,"rb",&Size)
需不要替换呢?

我的处理是把这部分代码直接去掉了,因为现在在Android平台上用CCFileUtils::sharedFileUtils()->getFileData是能够取到数据了的,所以不需要特殊处理了。文章已经作了修改,对这个作了说明。
廖定柏
你好,现在jpg格式还是不能加密么?
SunLightJuly

引用来自“廖定柏”的评论

你好,现在jpg格式还是不能加密么?

上述修改是已经支持了JPG格式的。
不过,MAC和IOS上面,要支持资源加密需要改的是另外几个文件。我都调试通过了,但还没有把相关的修改再写出来。这个周末我争取写完发出来吧。
阳光电信
请问下 如果是Json被加密了,那我要在哪个文件下面修改。 就是读取文件后对Json先进行解密。
SunLightJuly

引用来自“阳光电信”的评论

请问下 如果是Json被加密了,那我要在哪个文件下面修改。 就是读取文件后对Json先进行解密。

Json我没有试过。你是调用了相关的Json解析接口吗?可能需要自己找一下修改的地方了。
阳光电信

引用来自“SunLightJuly”的评论

引用来自“阳光电信”的评论

请问下 如果是Json被加密了,那我要在哪个文件下面修改。 就是读取文件后对Json先进行解密。

Json我没有试过。你是调用了相关的Json解析接口吗?可能需要自己找一下修改的地方了。

哦 谢谢 那我等你的回复!13
SunLightJuly

引用来自“阳光电信”的评论

引用来自“SunLightJuly”的评论

引用来自“阳光电信”的评论

请问下 如果是Json被加密了,那我要在哪个文件下面修改。 就是读取文件后对Json先进行解密。

Json我没有试过。你是调用了相关的Json解析接口吗?可能需要自己找一下修改的地方了。

哦 谢谢 那我等你的回复!13

你用的是Quick-x的Json接口吗?我看了一下,它并不是对文件进行操作的啊。你完全可以自己读取文件内容,解密后再调用的啊
阳光电信

引用来自“SunLightJuly”的评论

引用来自“阳光电信”的评论

引用来自“SunLightJuly”的评论

引用来自“阳光电信”的评论

请问下 如果是Json被加密了,那我要在哪个文件下面修改。 就是读取文件后对Json先进行解密。

Json我没有试过。你是调用了相关的Json解析接口吗?可能需要自己找一下修改的地方了。

哦 谢谢 那我等你的回复!13

你用的是Quick-x的Json接口吗?我看了一下,它并不是对文件进行操作的啊。你完全可以自己读取文件内容,解密后再调用的啊

恩! 确实是这样子的,哈哈 ,一时没反应过来!
sdada1231
怎么加载并执行加密的图片文件呀,我看加载加密的文件的方式是bool AppDelegate::applicationDidFinishLaunching()
02
{
03
...
04

05
CCLuaStack *pStack = pEngine->getLuaStack();
06

07
// 如果设置了 -e 和 -ek 要加上下面这句
08
// pStack->setXXTEAKeyAndSign("aaa", 3);
09
// 如果设置了 -e 和 -ek -es 则要加上下面这句
10
pStack->setXXTEAKeyAndSign("aaa", 3, "XT", 2);
11
// load framework
12
pStack->loadChunksFromZip("res/framework_precompiled.zip");
13
pStack->loadChunksFromZip("res/game.zip");
14
pStack->executeString("require 'main'");
15

16
return true;
17
}
这样的
那怎么加载加密的图片那?
SunLightJuly

引用来自“sdada1231”的评论

怎么加载并执行加密的图片文件呀,我看加载加密的文件的方式是bool AppDelegate::applicationDidFinishLaunching()
02
{
03
...
04

05
CCLuaStack *pStack = pEngine->getLuaStack();
06

07
// 如果设置了 -e 和 -ek 要加上下面这句
08
// pStack->setXXTEAKeyAndSign("aaa", 3);
09
// 如果设置了 -e 和 -ek -es 则要加上下面这句
10
pStack->setXXTEAKeyAndSign("aaa", 3, "XT", 2);
11
// load framework
12
pStack->loadChunksFromZip("res/framework_precompiled.zip");
13
pStack->loadChunksFromZip("res/game.zip");
14
pStack->executeString("require 'main'");
15

16
return true;
17
}
这样的
那怎么加载加密的图片那?

按这个方式修改后,加密的图片就可以直接用了,和没加密的图片一样使用,不需要额外的加载工作

sdada1231

引用来自“sdada1231”的评论

怎么加载并执行加密的图片文件呀,我看加载加密的文件的方式是bool AppDelegate::applicationDidFinishLaunching()
02
{
03
...
04

05
CCLuaStack *pStack = pEngine->getLuaStack();
06

07
// 如果设置了 -e 和 -ek 要加上下面这句
08
// pStack->setXXTEAKeyAndSign("aaa", 3);
09
// 如果设置了 -e 和 -ek -es 则要加上下面这句
10
pStack->setXXTEAKeyAndSign("aaa", 3, "XT", 2);
11
// load framework
12
pStack->loadChunksFromZip("res/framework_precompiled.zip");
13
pStack->loadChunksFromZip("res/game.zip");
14
pStack->executeString("require 'main'");
15

16
return true;
17
}
这样的
那怎么加载加密的图片那?

引用来自“SunLightJuly”的评论

按这个方式修改后,加密的图片就可以直接用了,和没加密的图片一样使用,不需要额外的加载工作

谢谢了,我知道怎么弄了

G0561
请教下, 你这个加密的方法,适用纯c++ 的cocos2dx 吗
SunLightJuly

引用来自“G0561”的评论

请教下, 你这个加密的方法,适用纯c++ 的cocos2dx 吗
可以的,这就是在C++下做的修改。不过你可能要自己集成一下XXTEA的解密代码。另外,如果你用的cocos2dx不是2.2.x版本,要修改的地方不一样,需要自己去找出来。
_beap
请教一下,我在使用你的pack_files进行图片加密的时候,出现了Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 72 bytes) in /Users/craig/workspace/quick-cocos2d-x/bin/lib/quick/xxtea.php on line 325,我只加密了一张图,大小是 5MB。这是怎么回事呢?
SunLightJuly

引用来自“_beap”的评论

请教一下,我在使用你的pack_files进行图片加密的时候,出现了Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 72 bytes) in /Users/craig/workspace/quick-cocos2d-x/bin/lib/quick/xxtea.php on line 325,我只加密了一张图,大小是 5MB。这是怎么回事呢?
5M文件有点大,php解析时内存不够了。你在pack_files.php文件里加一句:ini_set(”memory_limit”, ”128M”);
80后小子
请问一下,现在时间的版本是不是运行一下你给的那个bat命令就行了,我发现最新的quick源码路径下没有参考你写的哪些代码,是不是现在的版本还得按照你的步骤改一下c++的实现代码啊?
SunLightJuly

引用来自“80后小子”的评论

请问一下,现在时间的版本是不是运行一下你给的那个bat命令就行了,我发现最新的quick源码路径下没有参考你写的哪些代码,是不是现在的版本还得按照你的步骤改一下c++的实现代码啊?
你指的最新版本是哪一个?如果是2.2.5,不需要再自己加C++代码了。如果是V3,因为底层引擎载入图片的接口变化比较大,所以修改的地方不一样了,现在还没有时间去修改。我后面会再作一个针对V3的修改来支持加密图片的读取。
zhmx
楼主你好。很高兴看到你这篇文章。我按照教程配置修改了,但是还是出现了图格式错误的问题。
pack_files.bat -i res -o resSec -ek 123456 -es 654321 使用这个打包了png图片
我已经在Image::initWithImageFile里面改成 HelperFunc::getData(_filePath);,然后在appdelegate.cpp里面的applicationDidFinishLaunching加了
stack->setXXTEAKeyAndSign("123456", strlen("123456"), "654321", strlen("654321"));。但是就是有问题
[LUA ERROR] ASSERT FAILED ON LUA EXECUTE: unsupport image format!
请指导。
rabee
quick3.3final 改了,但是编译不过去,这个如何解决呢?
×
SunLightJuly
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: