凡事有个意图,对游戏关卡文件进行加密的主要目的就是防止被别人二次山寨
当然,仅仅根据游戏关卡文件就山寨出整个游戏来是不可能的事情,
但是游戏关卡文件的结构还是能够透露出相当多的信息,
为防万一,同时也为了让自己在软件安全方面练练手,我选择对游戏关卡文件加密。
次非空穴来风,因为我自己就干过不少类似的事情,看哪个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;
@end
BYSecurity.mm
//
// BYSecurity.mm
// HungryBear
//
// Created by Bruce Yang on 12-5-26.
//
#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