cocos2d-x学习笔记19:记录存储3:使用摘要算法进行存档校验 推荐
2012-05-24 21:49
1011 查看
引子
我在《cocos2d-x学习笔记16:记录存储1:CCUserDefault 》中提到过CCUserDefalut做存档的种种缺陷,其中之一就是明文存储,玩家可以直接修改存档。
本文将探讨如何使用摘要算法进行存档校验的方法。
准备工作
摘要算法很多,算法内容都是公开的。所以网络上有很多现成的算法库,最有名的是Crypto++,该库支持大量对称加密,非对称加密,和摘要算法。不过这库太庞大了,我们只是用一个简单的摘要算法,就先不用这玩意了。
我选择了SHA1,库从这个地址下载:
http://tamale.net/
打开后发现非常简洁,只有两个源代码(sha1.cpp,sha1.h),还有一个是测试代码(testsha1.cpp)。
我们先新建一个工程名为TestSha,然后把源代码导入。
然后为了方便调试,我们需要printf,cocos2d-x中打开printf的方法如下:
在代理函数 bool AppDelegate::applicationDidFinishLaunching() 里开头添加以下代码:
别忘了加头文件 #include <tchar.h>
然后你就可以使用printf啦,哇咔咔。
如何用SHA1做存档校验
我们使用如下代码写入存储记录
执行结果如下:
现在我们写一个读取校验
执行结果如下:
可以看到,校验是没有问题的
破解测试
现在我们手动修改存档文件UserDefault.xml,将string_value的值修改为test string crack。
运行结果如下:
校验不通过,玩家修改了存档。
思路
1.摘要算法即从原文中提取校验码,在读取存档时,进行校验。如果原文修改,校验码变化,则校验不通过。
2.因为摘要算法都是公开的,在使用时,我们会在输入待校验数据时,多输入一个key,这个key是隐藏在编码中的,除非玩家有很高超逆向工程技术,能反编并找到key,但我们一样可以调整Key的算法,以及提前对数据样本进行混淆。这种加密强度足以应付一般单机游戏的开发了。网游存档是在服务器端的,而且需要传输校验,所以我们也不考虑本地存档加密了。
实际中的使用
以上只是演示代码,在实际使用时,我们还需注意:
1.为了方便,演示中我只使用了字符串,对于bool,int等类型,你可以自己封装函数,进行校验,这样比较方便。
2.在编写的校验代码中,增加一个开关——随时打开和关闭校验。这样做的好处是,在校验关闭状态,测试人员可以直接修改存档,方便测试。哈哈哈,这就是把明文存档劣势,直接变为开发时的优势的思维转换哦。
3.实际使用时,校验码是要写入到存档中的,在读取存档时,顺便读取校验码,进行校验。
参考文献
《cocos2d-x 实现printf 输出结果,方便调试》
我在《cocos2d-x学习笔记16:记录存储1:CCUserDefault 》中提到过CCUserDefalut做存档的种种缺陷,其中之一就是明文存储,玩家可以直接修改存档。
本文将探讨如何使用摘要算法进行存档校验的方法。
准备工作
摘要算法很多,算法内容都是公开的。所以网络上有很多现成的算法库,最有名的是Crypto++,该库支持大量对称加密,非对称加密,和摘要算法。不过这库太庞大了,我们只是用一个简单的摘要算法,就先不用这玩意了。
我选择了SHA1,库从这个地址下载:
http://tamale.net/
打开后发现非常简洁,只有两个源代码(sha1.cpp,sha1.h),还有一个是测试代码(testsha1.cpp)。
我们先新建一个工程名为TestSha,然后把源代码导入。
然后为了方便调试,我们需要printf,cocos2d-x中打开printf的方法如下:
在代理函数 bool AppDelegate::applicationDidFinishLaunching() 里开头添加以下代码:
_tsetlocale(LC_ALL,_T("")); ::AllocConsole(); ::freopen("conout$","w",stdout);
别忘了加头文件 #include <tchar.h>
然后你就可以使用printf啦,哇咔咔。
如何用SHA1做存档校验
我们使用如下代码写入存储记录
#define TEXT1 "test string" #define KEY "goldlion" SHA1 *sha1; unsigned char *digest; CCUserDefault *save=CCUserDefault::sharedUserDefault(); save->setStringForKey("string_value",TEXT1); sha1=new SHA1; sha1->addBytes(TEXT1,strlen(TEXT1));//输入数据 sha1->addBytes(KEY,strlen(KEY));//输入数据 digest=sha1->getDigest();//获取校验码 SHA1::hexPrinter(digest,20);//打印16进制校验码到控制台 printf("\n"); delete sha1; free(digest);
执行结果如下:
现在我们写一个读取校验
#define TEXT1 "test string" #define KEY "goldlion" SHA1 *sha1; unsigned char *digest; CCUserDefault *save=CCUserDefault::sharedUserDefault(); std::string str=save->getStringForKey("string_value"); sha1=new SHA1; sha1->addBytes(str.c_str(),str.length());//输入数据 sha1->addBytes(KEY,strlen(KEY));//输入数据 digest=sha1->getDigest();//获取校验码 SHA1::hexPrinter(digest,20);//打印16进制校验码到控制台 printf("\n"); delete sha1; free(digest);
执行结果如下:
可以看到,校验是没有问题的
破解测试
现在我们手动修改存档文件UserDefault.xml,将string_value的值修改为test string crack。
运行结果如下:
校验不通过,玩家修改了存档。
思路
1.摘要算法即从原文中提取校验码,在读取存档时,进行校验。如果原文修改,校验码变化,则校验不通过。
2.因为摘要算法都是公开的,在使用时,我们会在输入待校验数据时,多输入一个key,这个key是隐藏在编码中的,除非玩家有很高超逆向工程技术,能反编并找到key,但我们一样可以调整Key的算法,以及提前对数据样本进行混淆。这种加密强度足以应付一般单机游戏的开发了。网游存档是在服务器端的,而且需要传输校验,所以我们也不考虑本地存档加密了。
实际中的使用
以上只是演示代码,在实际使用时,我们还需注意:
1.为了方便,演示中我只使用了字符串,对于bool,int等类型,你可以自己封装函数,进行校验,这样比较方便。
2.在编写的校验代码中,增加一个开关——随时打开和关闭校验。这样做的好处是,在校验关闭状态,测试人员可以直接修改存档,方便测试。哈哈哈,这就是把明文存档劣势,直接变为开发时的优势的思维转换哦。
3.实际使用时,校验码是要写入到存档中的,在读取存档时,顺便读取校验码,进行校验。
参考文献
《cocos2d-x 实现printf 输出结果,方便调试》
相关文章推荐
- cocos2d-x学习笔记17:记录存储2:SQLite基本使用 推荐
- cocos2d-x学习笔记17:记录存储2:SQLite基本使用
- cocos2d-x学习笔记17:记录存储2:SQLite基本使用
- cocos2d-x学习笔记17:记录存储2:SQLite基本使用
- cocos2d-x学习笔记16:记录存储1:CCUserDefault 推荐
- cocos2d-x学习笔记:记录存储1:CCUserDefault
- Cocos2d-X 学习笔记 16 使用Base64算法对Cocos2dX自带CCUserDefault游戏存储数据编码加密
- MVC使用Log4Net进行错误日志记录学习笔记4
- java学习笔记——使用JDBC,对数据库进行增删改查(方案一)【推荐】
- cocos2d-x学习笔记(八)使用NDK自带的iconv进行编码转换
- cocos2d-x学习笔记16:记录存储1:CCUserDefault
- MVC使用Log4Net进行错误日志记录学习笔记4
- cocos2d-x学习笔记16:记录存储1:CCUserDefault
- cocos2d-x学习笔记16:记录存储1:CCUserDefault
- (转)cocos2d-x学习笔记14:粒子系统1:简介&工具使用
- 微软企业库4.1学习笔记(十四)缓存模块2 使用缓存模块进行开发
- 【cocos2d-x从c++到js】17:使用FireFox进行JS远程调试 推荐
- 记录我的学习笔记-Java-log4j2的使用
- JUnit学习笔记19---对数据库应用程序进行单元测试3
- 深度学习笔记之使用Faster-Rcnn进行目标检测 (实践篇)