How to secure data from hacking?

Hello guys. Is there any way to make data more safe from editing by user? Now I am using UserDefault, and it’s not safe, because everybody can just open UserDefault.xml and edit it.

1 Like

I see 2 options:

  1. Use flatbuffers (they are implemented in cocos2d-x) or protocol buffers or Cap’n Proto etc…
  2. Use json or xml files to store data. Before storing data encrypt it (use variable name, value and password for that variable), when retrieving data decrypt it. If there is an error decrypting info just use default value like 0 or something and reset user data.
1 Like

Hello. Thanks for the answer, but I have a couple of questions. I included “flatbuffers.h”. I think I need to create the file or read from it if it is already created, than create FlatBufferBuilder object depending on file, and editing it, and after that save FlatBufferBuilder object to that file. Is my understanding correct? So if it is - how to create the file in cocos2dx and what type should it be for my binary data? How to work properly with the object? How to save there different types of data like int and bool?

You will find all info here https://google.github.io/flatbuffers/index.html

Basically follow this route

  1. Write your schema.
  2. Generate your schema c++ header.
  3. Include header in your game
  4. Create flatbuffers object.
  5. Check if there is file where you save flatbuffers binary
  6. If file exists read data, if not then create that file.
  7. When you change data for example increase level save flatbuffers object to that file

To create file I use flatbuffers::SaveFile function. I save it as player.data.
Here is info how to work with object https://google.github.io/flatbuffers/md__cpp_usage.html

If you need a server anyway, your best bet is to store data server-side, like all online games do nowadays.

If you don’t need a server, using one just to secure data may well be overkill.

Ask yourself the question: is it really worth it? On both iOS and Android (probably Windows Phone too), non-rooted devices won’t be able to edit files saved in the app, so what you do to secure data will only be useful for rooted devices, which may well be a tiny minority of your users.

We use encrypted SQLite3 databases to secure our game data.

I’d suggest using UserDefault only for preferences like “turn music off” or “SFX Volume to 50%” instead of your saved game data.

@corytrese, can you please provide more info on how to use encrypted SQLite3 db in game?

We use wxsqlite3 for secure data. There are more details on the WIKI page.
http://www.cocos.com/doc/tutorial/show?id=2151 (Chinese, not find an english version)

BTW, I use it for iOS, Android&Mac, It works great. But I have no idea how to add it to windows, Anyone know it?

1 Like

@Greenhouse – sure I can do my best to explain.

While we do not use it ourselves, wxsqlite3 is a fantastic solution. wxSQLite3 is a C++ wrapper around the public domain SQLite database.

To make effective use of SQLite db in a game, you need a few elements in your Cocos2d-x project.

  1. sqlite3.c
  2. A C++ wrapper around sqlite3
  3. a game library to manage databases / hold queries
  4. [optional] an encryption module for sqlite3.c

You’ll get the “amalgamation” version of sqlite3.c which makes it easy to build inside of Cocos2d-x. You can optionally patch this version of sqlite3.c to provide encryption, if your C++ wrapper does not.

Your C++ wrapper may add features, or it may simply provide C++ style wrappers around sqlite3 functions and behaviors (for example, error reporting and query formatting.) wxsqlite3 is one option, CppSQLite3 is another option.

You’ll want to create C++ classes of your own that wrap individual databases. I have one called DBGameMaster and one called DBSavedGame. The GameMaster database contains a table that lists all of the player’s saved games (as well as global things like settings, high scores, social media logins, etc.) The main table for GameMaster is the list of saved games – this is used so the player can pick which saved game to connect to. That is where DBSavedGame comes in. This class is capable of reading, writing and creating new SaveGame databases.

In our games we need to store a lot of data. Where the player’s buildings are, where their ships are, what upgrades they have, what ship designs, trade routes, treaties, etc. We also have to store all of the enemy AI state and logic. That means that the SavedGame database contains about 70 tables. All of the queries to insert, update, select and delete all of those tables are in the DBSavedGame C++ class, which wraps calls to the SQLite wrapper, which communicates with the low level sqlite3.c interface.

1 Like

I’m currently looking for a solution to protect UserDefaults xml file, and what you’ve described will probably be overkill in my case. Nevertheless it’s good to know about db option. Thanks for interesting info.

In that case, you will want to encrypt the values, not the storage layer.

Leave UserDefaults’s implementation alone if you can and encrypt the values you store into the XML.

That way only the secured values need to be encrypted, and your solution is portable as you upgrade Cocos2d-x or replace the backend for UserDefault.

@corytrese, I probably will replace UserDefaults xml file with FlatBuffers binary file as was suggested by @Edvinas as it seems much more secure way to hold player data on client. Although, there is one thing that doesn’t clear to me. Is it enough (from security perspective) to hold player’s data in FlatBuffers binary file or I need to encrypt it as well to increase security?

Bare in mind that UserDefaults is not unlimited in size, on Android i think its capped on 2mb, i’m not sure about iOS. If you have a lot of data my suggestion is to use SQLite with encryption, it is easier to maintain and extend, and encryption is really easy to setup.

1 Like

Hi @milos1290,

I have way smaller amount of data to store, ~128 bytes and my only concern is to store it in a safe place to avoid any frauds.

But I’ll definitely consider to use SQLite with encryption on larger scale game.

For current game I’m looking for a safe replace to UserDefaults xml storage.

In that case go for UserDefaults with xxtea encryption. But consider your future data model, if you think that it might extend more, go for SQLite in the first place.

Can please provide more info on how to implement it in cocos2d-x game?

From xxtea example on github:

#include <stdio.h>
#include <string.h>
#include <xxtea.h>

int main() {
    const char *text = "Hello World! 你好,中国!";
    const char *key = "1234567890";
    size_t len;
    unsigned char *encrypt_data = xxtea_encrypt(text, strlen(text), key, &len);
    char *decrypt_data = xxtea_decrypt(encrypt_data, len, key, &len);
    if (strncmp(text, decrypt_data, len) == 0) {
        printf("success!\n");
    }
    else {
        printf("fail!\n");
    }
    free(encrypt_data);
    free(decrypt_data);
    return 0;
}

Is it safe enough to hold key as a string literal in source?

So the idea is to either use json (if you have structure) or just plain strings, encrypt it and save to UserDefaults under one key.

Checkout xxtea header (its in external folder) it basically have only two methods, xxtea_encrypt and xxtea_decrypt. By default xxtea is not included to build list in XCode and Android.mk file, so you will have to modify cocos2d-x Android.mk file and cocos2d-x XCode project.

1 Like

How to keep the key itself in safe?

Here is the discussion regarding that question on so

I store in UserDefaults high-score int value of the player encrypted with xxtea. Now, some cheater opens Cocos2dxPrefsFile.xml and start editing the value for high-score key. What will I get next time I decrypt high-score stored value then?

Well, there is nothing you can do about it. You can check if data is a number and if it is not just clear the prefs and reset the game to beginning. That will learn him.