LoginSignup
35
39

More than 5 years have passed since last update.

【Cocos2d-x】Luaスクリプトを簡単に暗号化

Last updated at Posted at 2015-01-11

はじめに

Cocos2d-xで開発する時に、言語は何を使っているでしょうか?
C++が多いような気がしますが、手っ取り早く開発するには、Lua、JavaScriptも捨てがたいかと思います。
最近ではCocos Code IDEを使えば開発もし易いですね。

ただ、スクリプト言語で開発する場合、そのままだと生のスクリプトファイルが
アプリのパッケージに含まれてしまうため、コードの解析が容易になってしまいます。
これは企業で開発している場合は致命的ですし、個人開発でも避けたい問題です。
この問題を解決するには、スクリプトファイルを暗号化するのが良さそうです。

Cocos2d-xのcocosコマンドには、スクリプトファイルのコンパイル・暗号化のコマンドが用意されており、
コマンド一発で暗号化できます。

luacompile コマンド

Luaの場合、luacompileというコマンドを使います。
リファレンスはここです。

このコマンドは、Luaスクリプトをコンパイルし、バイトコードに変換してくれるコマンドで、
オプションを指定することで暗号化までやってくれます。

Luaスクリプトのコンパイル

まずは暗号化はせず、コンパイルだけで実行してみます。

mv src _src
cocos luacompile -s _src -d src

luacompileコマンドでは、読み込み元ディレクトリ(-s)と、出力先ディレクトリ(-d)を指定するので、
srcディレクトリを_srcにリネームしてから実行しています。
実行後にsrcディレクトリを見ると、.luacという拡張子のファイルが出来ているはずです。
これがバイトコードに変換されたファイルになります。

バイトコードで実行してみる

それではAndroidでゲームを実行してみましょう。Androidで

cocos run -p android

ちなみにAppDelegate.cppの中でsrc/main.luaを指定しているのですが、
このファイル名は.luacに変更しなくても問題なく動作します。
詳細はCocos2dxLuaLoader.cppを見ればわかりますが、
.lua.luacのどちらか存在している方のファイルを実行しているからです。

さて、勘のいい方はお気づきでしょうが、iOSではLuaバイトコードは実行できません。
これはCocos2d-xの問題ではなく、LuaJITがarm64に対応していないということが原因のようです。
Luajit bytecode not supported on arm64?

(追記)Cocos2d-x 3.6でLuaJIT2.1にアップデートされたようです。未確認ですが、これによりarm64に対応されているはずです。

試しにXcodeでターゲットをiOSではなくMacにしてみると、問題なくロードすることができます。

luacompileでは、コンパイルせずに、テキストのまま暗号化することもできるため、その方法を後述します。

Luaスクリプトの暗号化

次はコンパイルしたファイルをさらに暗号化してみましょう。

ちなみに暗号化はXXTEAというアルゴリズムを使っているようです。
C++だとxxtea.cppというソースで複合化を実行しています。
cocosコマンドは、Pythonスクリプトの中でXXTEAの暗号化処理が実装されています。

暗号化するには、luacompileコマンドに、-eというオプションを付けるだけです。

cocos luacompile -s _src -d src -e

これでバイトコードをさらに暗号化してくれます。簡単ですね。

暗号化キーを指定しないと、デフォルトのキー(2dxLua)になってしまうので、
暗号化キーを指定しましょう。-kでキーを指定します。

cocos luacompile -s _src -d src -e -k 1234567890ABCDEF

xxtea.cppを見ると、NULL文字で埋めて16桁にしているようなので、16桁で指定するのが良さそうです。

-s(encryptsign)というオプションもあるのですが、これはデフォルト(XXTEA)のままでも良いと思います。
暗号化する前にファイル内に指定した文字を埋め込んで、複合化の時にその文字と一致するかを
チェックしているようです。

さて、暗号化ではキーを指定するので、複合の際も同じキーを指定する必要があります。
AppDelegate.cppAppDelegate::applicationDidFinishLaunchingに、
以下のコードを追加しましょう。

AppDelegate.cpp
bool AppDelegate::applicationDidFinishLaunching()
{
    auto engine = LuaEngine::getInstance();
    ScriptEngineManager::getInstance()->setScriptEngine(engine);
    lua_State* L = engine->getLuaStack()->getLuaState();
    lua_module_register(L);

    // If you want to use Quick-Cocos2d-X, please uncomment below code
    // register_all_quick_manual(L);

    // ここから追加 ////////
    const char *key = "1234567890ABCDEF";
    const char *sign = "XXTEA";
    engine->getLuaStack()->setXXTEAKeyAndSign(key, (int)strlen(key), sign, (int)strlen(sign));
    // ここまで追加 ////////

    if (engine->executeScriptFile("src/main.lua")) {
        return false;
    }

    return true;
}

setXXTEAKeyAndSignでキーをセットすることで、Luaファイルをロードする際に、
複合化の処理が実行されるようになります。

Luaの中でrequireしたファイルはどうなるの?と疑問に思うかもしれません。
Cocos2d-x LuaBindingsでは、requireが実行される際、Cocos2dxLuaLoader.cppの中の
cocos2dx_lua_loaderという関数を実行して、ファイルを読み込んでいます。
この関数の中で複合化処理が実行されるため、requireしたファイルも問題なく複合化されます。
逆に、setXXTEAKeyAndSignをでキーをセットしている場合は、暗号化されていないファイルは
reqiureでエラーになります。

テキストのまま暗号化

iOSでは、Luaバイトコードはロードできないと述べました。
そのためiOSでアプリをリリースしたい場合は、テキストのまま暗号化のみを行うことになります。
コンパイル処理をスキップするには、--disable-compileオプションを指定します。

cocos luacompile -s _src -d src -e -k 1234567890ABCDEF --disable-compile

これで暗号化のみが実行されます。

こうしておけば、暗号化してもiOS/Android両方で実行できるようになります。

おわりに

スクリプトファイルの暗号化については、知りたい方も多いかと思うのですが、
意外に情報が少なかったため、書いてみました。

以上です。

35
39
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
39