Cocos Creatorのユーザーデータ暗号化

公式のユーザーデータ保存は参考1の通りですが、今回やりたいこととの違いは、①TypeScriptでの実装、②暗号化部分の情報補足の2点になります。

プロジェクトルートで下記コマンドでencryptjsをインストールすることができます。

npm i encryptjs

npmコマンドが見つからない場合はHomebrewなどで以下のようにインストールできます。

brew install node

encryptjsをインストールできたら、プロジェクトルート/node_modules/encryptjsのディレクトリーが増えると思います。

その下の「algo.js」と「encryptjs.js」があるはずですので、それらをドラックしてCocos Creatorの「Script」のようなフォルダに入れます。
※「Script」の下で、サードパーティライブラリ専用のサブフォルダを作り、その中に入れたほうがいいかもしれません。例として、Script/Libraryでいきます。

そしたら、こんな感じでユーザーデータ保存用クラス(UserData.ts)を作れます。

const {ccclass, property} = cc._decorator;
import * as Encrypt from '../Library/encryptjs'; // ここで先程追加したライブラリをインポート

@ccclass
export default class UserData extends cc.Component {

    private static _instance:UserData;
    private static secretKey:string = 'abab123'; // 暗号キー

    private constructor() {
        super();
    }

    // シングルトンの例
    public static get instance():UserData {
        if (!this._instance) {
            cc.log("Init UserData");
            this._instance = new UserData();
            this._instance.save();
            this._instance.load();
        }
        return this._instance;
    }

    public save() {
        // サンプルデータを作成
        let userData = {
            name: 'Tracer',
            level: 1,
            gold: 100
        };

     // JSONを文字列に変換
        let dataString = JSON.stringify(userData);
        cc.log("data 1: " + dataString);
     // 暗号化
        let encrypted = Encrypt.encrypt(dataString, UserData.secretKey, 256);
        cc.log("encryptd data: " + encrypted);
        // ローカルに保存
        cc.sys.localStorage.setItem('UserData', encrypted);
    }

    public load() {
        // ローカルに保存したデータの読込み
        let cipherText = cc.sys.localStorage.getItem('UserData');
        // 復号化
        let decrypted = Encrypt.decrypt(cipherText, UserData.secretKey, 256);
        // JSON解析
        let userData2 = JSON.parse(decrypted);
        cc.log("data 2 :" + JSON.stringify(userData2)); // ログ出力のために文字列に変換
    }
}

ここでは初期化のところに保存と読込みやってますが、必要に応じて場所を変えるといいでしょう。
実行してUserDataが初期化されると以下のようなログが出力されると思われます。

[Log] Init UserData (UserData.js, line 35)
[Log] data 1: {"name":"Tracer","level":1,"gold":100} (UserData.js, line 52)
[Log] encryptd data: iwPrvkfnzVuqXcF48BFHIXyOYwGJ2Uvma/yNL3dx2iPyWyQmQ/DEhB9POIlt1g== (UserData.js, line 54)
[Log] data 2 :{"name":"Tracer","level":1,"gold":100} (UserData.js, line 61)

ユーザーデータの暗号化は以上です。

ところで、最終的にネイティブで実行されるコードはJavaScriptである故に、バイナリにならず、.jscの付いたソースコードを難読化したものにとどまります。
ソースコードの難読化は暗号化ではなく、ソースコードの復元は比較的に容易にできるはずです。
さらに、もしCocos CreatorでWebブラウザ向けのゲームを作るなら、難読化すらされず(難読化されたらブラウザが読めなくなるため)、ソースコードそのまま公開されます。
これはCocosだけの問題ではなく、どのエンジンでも、プラグインなしではHTML+JavaScriptが主流ですから。

つまり、ユーザーのデータを暗号したところ安全ではなく、実はパスワード(暗号キー)がバレバレであることを注意していただきたいです!

じゃあ、なんで暗号化なんかするんだ?!というと、周知の通り、暗号化と言っても、どこまでやれば本当に安全であるかの話になればキリがないので、ここの暗号化によって、そう簡単にチートされることはないだろうと、平文保存よりは多少マシであるだろうとのことが言えると思います。
実際の案件は暗号化の実装難易度や暗号/復号による負荷などでやり方が決まると思いますので、この方法はサーバーを介さず、手軽でやれるところがいいと思います。

何か誤りや質問があれば、お気軽にコメントください!^^b

参考:
  1. User Data Storage
  2. encryptjs
  3. How to install NodeJS and NPM on Mac using Homebrew
  4. How to import js-modules into TypeScript file?

Cocos Creatorがコンパイルできない問題の対処法

環境:
macOS High Sierra: v10.13.6
Xcode: v10.0
Cocos Creator: v2.0.4

Cocos Creatorでビルド画面でプラットフォームをiOS選択し、「Build」ビルドは無事終わることができますが、「Compile」では失敗します。

ログを確認すると、以下の2行だけです。
Building mode: release
Update xcode please.

うぅん〜Xcodeは最新版のはずなのに。。。

調べてみたところ、簡単な方法はXcodeで直接プロジェクトを開けば良いです。
プロジェクトルート/build/jsb-link/frameworks/runtime-src/proj.ios_macの下にXcodeのプロジェクトファイルがあると思いますが、それを開けば普通に実行できます。

または、以下のスクリプトを修正することです。
/Applications/CocosCreator.app/Contents/Resources/cocos2d-x/tools/cocos2d-console/plugins/plugin_compile/project_compile.py

このファイルの476行〜480行あたりの下記部分をコメントアウトするといいようです。

        version = cocos.get_xcode_version()

        if version <= '5':
            message = MultiLanguage.get_string('COMPILE_ERROR_UPDATE_XCODE')
            raise cocos.CCPluginError(message, cocos.CCPluginError.ERROR_TOOLS_NOT_FOUND)

cocos creator次のバージョンでこれを修正してくれるといいんですが、もしそうでなければ、バージョンアップするたびにエンジンのソースコードを修正するのはちょっと、、、という方は直接Xcodeでコンパイルしたほうがいいではないでしょうか。

とりあえずエンジンのスクリプトにちょっとした不具合があったことと、直接Xcodeでコンパイルすれば問題ないということだけ知って一安心ですね。

参考

  1. Cannot compile on Mojave with Xcode 10
  2. creator编译发布ios 报 Update xcode please.
  3. Xcode升级到10.0后,cocos creator编译失败

Cocos Creator.app is damagedの対処法

10月17日にCocos Creator v2.0.4がリリースしたので、早速試そうとしましたが、下記のように
“CocosCreator.app” is damaged and can’t be opened. You should move it to the Trash.
のエラーが出ました。

CocosCreator.app is damaged and can't be opened

この場合は、インストールしたアプリを残し、ターミナルで以下のコマンドで解決できました。

xattr -rc /Volumes/Cocos\ Creator/CocosCreator.app

ちなみに、参考1の同じページで議論されているゲートキーパーを解除の方法ですが、つい昨日VirtualBoxインストールできなかった時に参考したサイト(参考2)で紹介されました。

普通「システム環境設定」⇒「セキュリティとプライバシー」を開くとこうなっているはずです。
Security & Privacy

下部の「ダウンロードしたアプリケーションの実行許可(Allow apps downloaded from)」のところでは、「すべてのアプリケーションを許可(Anywhere)」は出ていないと思います。

この時はターミナルで以下のコマンドを実行すると、「すべてのアプリケーションを許可(Anywhere)」が表示され、解除できるようになります。

sudo spctl --master-disable

また、元に戻す場合は以下です。

sudo spctl --master-enable
参考
  1. Damaged and can’t be open app error message
  2. Fixing ‘The Installation Failed’ VirtualBox Error on Mac High Sierra

Cocos CreatorのError:Cause: path may not be null or empty string. path=”問題

Cocos Creator(v2.0.2)でプロジェクトを新規作成して適当なシーンでAndroid実機での配置を確認したところ、Android Studio(v3.1.3)開いたらいきなり読み込み失敗です。
以下のようなエラーが出ました。

path may not be null or empty string. path=''

結論から言うと、Cocos Creatorのメニューから「Project」⇒「Build…」を選び、出てきたポップアップ中の「Platform」を「Android」にして、各種設定を調整した上でビルドすれば解決です。

特にここの「Keystore」のところ、「Use Debug Keystore」にチェック入れることが今回のポイントになります。
もちろん本番パッケージをビルドする際には本番用のKeystoreを入れる必要があります。


Cocos CreatorからiOSだけビルドしても、下記のところにAndroidなど他のプラットフォームのプロジェクトもが生成されます。
プロジェクトルート/build/jsb-link/frameworks/runtime-src

私はまずiOSの動作を確認したので、Androidのプロジェクトが既に作成されてると思い込んだことが今回の原因です。
実際ファイルがそこにありますからね。^^;

Android Studioでプロジェクトを読み込む時の詳細ログを見てみると、ここで引っかかったようです。

	at build_bf37h7qx9z4mihhuyxuow3w4l$_run_closure1.doCall(プロジェクトルート/build/jsb-link/frameworks/runtime-src/proj.android-studio/app/build.gradle:56)

実際そのファイルの56行あたりはこんな感じです。

    signingConfigs { # <=56行はここ

       release {
            if (project.hasProperty("RELEASE_STORE_FILE")) {
                storeFile file(RELEASE_STORE_FILE)
                storePassword RELEASE_STORE_PASSWORD
                keyAlias RELEASE_KEY_ALIAS
                keyPassword RELEASE_KEY_PASSWORD
            }
        }
    }

故にプロジェクトルート/build/jsb-link/frameworks/runtime-src/proj.android-studio/gradle.propertiesの下記の設定に辿り着きました。

RELEASE_STORE_FILE=
RELEASE_STORE_PASSWORD=
RELEASE_KEY_ALIAS=
RELEASE_KEY_PASSWORD=

Keystoreの設定がないんですね。
まだデバッグなのに、空でダメなの?と思いながらも設定してみました。
ところでここを正しいパスやパスワードを設定しても、また別のエラーで読み込むことができませんでした。

これは何かが違う!!
このゲームエンジンの人気が落ちたとは言え、一応それなりの人数が使ってるはずだから、こんなにいい加減なはずがないと思い、やっと冒頭のやり方に辿り着いた訳です。

そしてそのようなキーワードで検索しても、それらしい答えが見つからなかったので、ここでまとめてみました。

Cocos CreatorのビルドもUnityのように、選択したプラットフォームのみ出力したほうが良くないんですかね?!