好了,进入本文的主题——脚本加密:
Lua 是一个小巧的脚本语言。Lua脚本可以很容易的被C/C++代码调用,也可以反过来调用C/C++的函数,这使得Lua在应用程序中可以被广泛应用。不仅仅作为扩展脚本,也可以作为普通的配置文件,代替XML,Ini等文件格式,并且更容易理解和维护。在目前所有脚本引擎中,Lua的速度是最快的。这一切都决定了Lua是作为嵌入式脚本的最佳选择。
lua是明文形式,如果不对脚本进行处理,那么我们所写的代码将可能暴露给别人。
luajit来实现加密的目的。
这种其实并不是真正意义上的加密,而是用luajit把lua脚本编译成字节码。
首先我们来用luajit来实现脚本的编译。其实就是一句话:
luajit -b source des
其含义即把源代码编译成二进制文件,达到加密的目的
当然我们不可以每一个文件都来运行一遍,这样太麻烦,不符合我们程序员‘懒’的内涵。
第一种加密办法:利用xcode
这种方法的好处是新生产的文件结构依然是按照源码目录。
既然我们使用xcode作为IDE,那我们完全可以创建一个scheme来实现时时编译的目的。
利用xcode创建scheme步骤:
1.新建一个target 选择 external build system,build tool 选择 usr/bin/sh 即可。名称:build-lua
2.然后配置如下调用。
我把luajit -b source des利用python 扩展了一下, 基本的含义就是把遍历lua目录,分别编译脚本到新的目录。
# -*- coding: utf8 -*-
# this is single line comment
import os
import inspect
import ConfigParser
import re
import sys
import shutil
def findAllLuaFiles(dir):
targets = []
for f in os.listdir(dir):
p = os.path.join(dir, f)
if os.path.isfile(p):
targets.append(p)
else:
rs = findAllLuaFiles(p)
for rf in rs:
targets.append(rf)
return targets
def main():
from optparse import OptionParser
parser = OptionParser("usage: %prog [options]")
parser.add_option("-s", action="store", type="string", dest="source", help="specifies the source folder")
parser.add_option("-t", action="store", type="string", dest="target", help="specifies the target folder")
(opts, args) = parser.parse_args()
workingdir = os.path.dirname(inspect.getfile(inspect.currentframe()))
sourceDir = opts.source
targetDir = opts.target
if os.path.exists(targetDir):
shutil.rmtree(targetDir)
shutil.copytree(sourceDir, targetDir)
luaFiles = findAllLuaFiles(targetDir)
from string import Template
cmdTemplate = Template("/usr/local/bin/luajit -b $src $dist")
for lf in luaFiles:
command = cmdTemplate.substitute(src=lf, dist=lf)
print "[Compile]", command
os.system(command)
3.在我们的主程序中设置如下,把新建的build-lua 添加进来,使其在每次build的时候都能运行一遍。
4.最后我们还要删除掉源代码,(注意在程序使用过程中,需要require 的时obj/下的文件。
Ps:在lua脚本引用的时候需要requrie的是des 目录,不是source目录。
如果你嫌上面的方法繁琐的话,可以你可以试试quick-cocos2d-x gitHub地址为:https://github.com/dualface/quick-cocos2d-x
第二种加密办法:利用quick-cocos2d-x
Ps:quick-cocos2d-x 是最新版是基于cocos2dx2.2.3所以无法在cocos2dx3.0里面使用,除非仿写ccLuaStack.h/.cpp 对比发现工程量浩大。
设置加密密钥和加密签名,是将源目录直接打包成zip包。
quick 是 cocos2d-x 针对 Lua 的豪华套装威力加强版。 可喜的是,quick团队在年初被触控科技收购了,以后我们就可以时时看到稳定更新了。
quick 和 cocos2d-x 的主要区别有如下几点:
- 更完善的 Lua 支持,包括一个 Lua 框架对 C++ 接口进行了二次封装
- 补充了大量 cocos2d-x 没有提供,但游戏需要的功能
- 为提高开发效率,提供了 Objective-C 和 Java 的桥接模块,以及强化的 Windows/Mac 模拟器
本文接下来将要讲述的就是quick的新功能,脚本加密。
在quick-cocos2d-x-develop/bin/目录下存在多个sh脚本,今天我们需要用到的就是compile_scripts.sh
compile_scripts.sh中带有不少的参数,详情如下:
1、 -h 帮助。显示参数的解释及使用,英文的。
2、-i 源码目录。
3、-o 输出文件或目录。
4、-p 包前缀。
5、-x 不包含在内的包。如果你有些源文件不想被编译进去的话,将会用到这个参数,只能设置包(对应文件夹),不能指定到文件,多个包的话用,(逗号)隔开。示例:-x app.test,server,指的是app/test/.*,server/.* 这两个目录下的所有文件都不会被编译。
6、-m 编译模式。有两个值 :
-m zip 默认,生成的是zip格式文件;
-m files 生成的是一个个文件,不打包,这个时候-o参数指的就是输出的目录。
7、-e 加密模式。可以对编译后的文件再进行 XXTEA 加密,有两个值:
-e xxtea_zip 对应-m zip,对打包后的zip格式文件进行加密,之后再打包成zip格式。
-e xxtea_chunk 对编译后的文件加密,最后打不打包取决于-m。
8、-ek 加密密钥。对-e有效,且设置了-e之后一定要设置-ek。
9、-es 加密签名。对-e有效,默认值为"XXTEA",这个只是为了让引擎知道文件是否被加密过,意义不大,所以可不设置。
10、-ex 编译后的文件的后缀名。对-m files有效,默认值为"lua"。
11、-c 从一个文件加载参数列表。
12、-q 生成过程不输出信息。
使用步骤:
1.复制quick-cocos2d-x-develop/lib/cocos2d-x/scripting/lua/cocos2dx_support下的CCLuaStack.h 和CCLuaStack.cpp 替换程序cocos2dx相应的文件。
quick帮我们扩展了三个文件,也就是我编译加密需要的三个函数:
virtual int loadChunksFromZip(const char *zipFilePath);
virtual void setXXTEAKeyAndSign(const char *key, int keyLen);
virtual void setXXTEAKeyAndSign(const char *key, int keyLen, const char *sign, int signLen);
2.可以直接在终端运行如下命令,也可以利用scheme执行下面的命令,
compile_scripts.sh -i scripts -o files/desc.zip -e xxtea_zip -ek 123456 -es 654321
123456 为加密密钥
654321 为加密签名
3.在代码调用的时候:
bool AppDelegate::applicationDidFinishLaunching()
{
...
CCLuaStack *pStack = pEngine->getLuaStack();
// 第二,四参数分别为第一 三 字符串的长度
pStack->setXXTEAKeyAndSign("123456", 6, "654321", 6);
// load framework
pStack->loadChunksFromZip("res/framework_precompiled.zip");
pStack->loadChunksFromZip("res/game.zip");
...
}
4. 删掉源代码文件
好了,我们的脚本已经编译加密了,再也不用担心被抄袭了。