凡事有个意图,对游戏关卡文件进行加密的主要目的就是防止被别人二次山寨
当然,仅仅根据游戏关卡文件就山寨出整个游戏来是不可能的事情,
但是游戏关卡文件的结构还是能够透露出相当多的信息,
为防万一,同时也为了让自己在软件安全方面练练手,我选择对游戏关卡文件加密。
次非空穴来风,因为我自己就干过不少类似的事情,看哪个app 做的很好,
便会将 app 的内容导出到电脑里面,分析其所用的素材和框架,使用到了那些技术等等。
所以,这是相当有必要的,你不能假设其他人都是sb,
你得充分去实践怀疑论,尽最大可能去维护自己应有的权益。
ok,闲话不多说,进入正题:
对游戏资源文件的保护我发现以下那么几种方案:
1。将资源文件的2进制数据弄进代码里面,之前我有参照别人提出的这个思路写过一个小工具,
能够将资源文件转化为头文件。这份头文件到时候会无缝契合到程序里面去,性能不知道怎么样,
但是安全性多少还是有些的——对逆向不是很了解,所以话不敢说死~
2。第二个比较靠谱,也是不少人正在采用的:用现成的加密算法对资源文件进行加密。
具体流程:
我的游戏关卡文件是以xml形式存在的,
首先我在项目中书写一些代码,这部分代码的作用就是在真机测试app的过程中,
将 xml 文件加密后置入 app 的 Documents 目录下面。
当然,如果能新建一个 command line tool 项目隔离开来做是最好的,电脑的效率比ios 设备高了去了。
我这里也是偷懒了,不过置入项目中的话,今后再回来翻,可能会方便一点。
借助 iExplorer 将 Documents 目录中生成的加密好的关卡文件弄到电脑里面来,
用加密过的关卡文件将项目中之前未加密的关卡文件替换掉,再修改一下关卡加载模块,完工~
下面是一点儿相关的代码,后来我没有采用在游戏项目中对游戏关卡加密的方案,
如上所述,太麻烦了(我直接在我的关卡生成工具里面就把这步给完成了)~
相关代码:
BYSecurity.h
#import <Foundation/Foundation.h> #import "GCfg.h" #import "Rc4.h" #import "SecurityMacros.h" @interface BYSecurity : NSObject +(BYSecurity*) security; -(id) init; -(void) encryptAllLevels; @endBYSecurity.mm
// // BYSecurity.mm // HungryBear // // Created by Bruce Yang on 12-5-26. // Copyright (c) 2012年 EricGameStudio. All rights reserved. // #import "BYSecurity.h" @implementation BYSecurity +(BYSecurity*) security { return [[[self alloc] init] autorelease]; } -(id) init { if((self = [super init])) { } return self; } -(BOOL) writeApplicationData:(NSData*)data toFile:(NSString*)fileName { NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString* documentsDirectory = [paths objectAtIndex:0]; if(!documentsDirectory) { NSLog(@"Documents directory not found!"); return NO; } NSString *appFile = [documentsDirectory stringByAppendingPathComponent:fileName]; return ([data writeToFile:appFile atomically:YES]); } -(void) encryptAllLevels { return; // 0.关卡总数~ int levelTotalCount = [[GCfg getInstance] ifk:@"levelTotalCount"]; NSLog(@"levelTotalCount = %d", levelTotalCount); // 1.documents 目录的绝对路径~ NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString* documentsDir = [paths objectAtIndex:0]; if(!documentsDir) { NSLog(@"Documents directory not found!"); return; } NSString* bundlePath = [[NSBundle mainBundle] bundlePath]; for(int i = 0; i < levelTotalCount; ++ i) { // 1。不能仅仅凭借文件名就获取文件的内容,即使是在 ios 平台上面,读取到的 string 为 null~ // NSString* fileName = [NSString stringWithFormat:@"level_%d.xml", i]; // NSLog(@"fileName = %@", fileName); // NSString* fileContent = [NSString stringWithContentsOfFile:fileName // encoding:NSUTF8StringEncoding // error:nil]; // NSLog(@"%@", fileContent); // 2。正确写法~ NSString* fileName = [NSString stringWithFormat:@"level_%d", i]; // NSLog(@"fileName = %@", fileName); NSString* filePath = [NSBundle pathForResource:fileName ofType:@"xml" inDirectory:bundlePath]; NSString* fileContents = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; // NSLog(@"%@", fileContent); // 3。加密文件内容~ NSString* encryptedContents = [Rc4 HloveyRC4:fileContents key:SECURITY_KEY]; // 4。在 app 的 documents 目录下生成新的加密文件~ NSString* newFileName = [NSString stringWithFormat:@"lv%d.y3w", i]; NSString* newFilePath = [documentsDir stringByAppendingPathComponent:newFileName]; [[encryptedContents dataUsingEncoding:NSUTF8StringEncoding] writeToFile:newFilePath atomically:YES]; } } @end