Search Unity

Encrypt Savegames

Discussion in 'Scripting' started by Domvel, Nov 12, 2018.

  1. Domvel

    Domvel

    Joined:
    Sep 18, 2018
    Posts:
    24
    Hi there,

    I wondering how to handle savegames in Unity? Usually this should be encrypted. As a game engine I expected that Unity has buildin features to do this. But I don't found stuff about it. So I implemented a save game with the BinaryFormatter and / or JsonUtility. It works to serialize a class which stores the values.
    BUT how to encrypt this to avoid cheating? By using System.Security.Cryptography?
    I looking for a efficient but simple solution. Less code is more.
     
  2. dadude123

    dadude123

    Joined:
    Feb 26, 2014
    Posts:
    789
    Its not possible to protect save games from being modified (cheating).
    Everything the game could possibly do to the data, it has to undo when loading it again.
    And thus an attacker could simply do the same thing (the same operations) as well.

    Encryption does literally nothing. It takes like 5-10minutes to simply hook into the cryptography routines with cheat-engine or any other debugger of your choice to get the password and IV bytes.

    The good news is that in a single player game you don't have to care about people cheating as it won't influence others.

    If you have some sort of multiplayer component in your game and are actually concerned about cheating, then saving data on the client / the players computer is the wrong approach anyway. In multiplayer games only the server saves stuff. Or to put it into even more direct words, the actual game that is being played happens exclusively on the server, the client your players use just do the graphics and stuff around that (that's how it works in every MMO, and almost every shooter). That makes cheating impossible.

    Everything on the client can be hacked/cheated.

    If you just want some basic protection against noobs then yea, just save the file and then encrypt it. There are thousands of tutorials about that on the internet already, not sure why Unity would build something so simple (and specific) into the engine though...
    Assuming they did, I'd take just a few hours for tons of people to show up asking how to customize the system and do things differently, so what would even the point :p
     
    lordofduct likes this.
  3. Domvel

    Domvel

    Joined:
    Sep 18, 2018
    Posts:
    24
    Thanks for your post, but I have no idea why is this request always assumed to a 100% protected system. This isn't possible. Everybody should know it. Every system can be broke with a great ambition. But it is a difference to store your savegames as plaintext or encrypted binary. In best case with a hash to avoid lucky successively byte change attemptions. ... Whatever. This keeps the most people away.

    Sorry I did not specified my goal. :)
    I do not want a most secured savegame system for a online game. Just a simple savegame protection like all other games have. Indeed a proprietary format can be more secure.
    Maybe someone will decrypt the savegame and build a editor for cheating.

    I'm a bit disappointed that this topic is always blocked by people saying "oh, it's not secure. You can't protect your data." xD In fact it's a request to avoid plain-text save data. btw. BinaryFormatter is also plain-text with a bit byte coded values.

    Conclusion:
    Encrypt data by obfuscating. Develop your own encrypted savegame system. You can use C# AES as a good base. 100% protection is impossible. This should everybody know.
    For those who claim it is safe only against noobs: Let's bet you can't decrypt it. :p
     
  4. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
    I would ask first, is this strictly for single player?
    If so, why concern about cheating?
    You can encrypt saves, but players perhaps start using cheat engine, for whom is more determined.
    Let player do whatever they like with their purchased game.
     
  5. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Most games doesn't even encrypt it. Just don't store it as text / xml / json. (Any human-readable format).

    Do a binary serialization.
    So, most of the people won't be able to modify it via notepad.

    People that hack will hack it anyway. Singleplayer games doesn't need obfuscation / encryption, and you're simply wasting your development time.
     
    dadude123 and Antypodish like this.
  6. mholmes

    mholmes

    Joined:
    Dec 8, 2012
    Posts:
    414
  7. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Look up Xor obfuscation, and you can just as easily use it on strings as you can on byte arrays. The people who really know what they are doing you are not going to be able to stop with really anything, but this is super simple to implement and will deter pretty much anyone who is just casually looking at what they can play with.
     
  8. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,697
    Last edited: Nov 13, 2018
    Domvel likes this.
  9. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    Something I used in the past is compression, i.e. save the data as png (using unity standard api) - good enough as a simple barrier
     
  10. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    - What are those images weighting few gigabytes? (c) User
    Boom! Deleted.
     
  11. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    not sure what you are talking about - this does not make much sense to me.
     
  12. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
    I will try translate for you.
    If I see some random gibberish images, which suppose to be saved data, but I don't know about it, yet the take a lot of space, I will be keen to delete them, to release space.
     
    xVergilx likes this.
  13. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    who says this will happen?
    - just call what you save "savegame.dat"
    - they should take less space than uncompressed

    Code (CSharp):
    1.         // the serialized data you want to save
    2.         byte[] saveData;
    3.      
    4.         // compress the data using a 4 color channel texture
    5.         int dim = Mathf.CeilToInt(Mathf.Sqrt(Mathf.CeilToInt(saveData.Length / 4)));
    6.         Texture2D t = new Texture2D(dim, dim, TextureFormat.RGBA32, false);
    7.         byte[] temp = new byte[dim*dim*4];
    8.         System.Array.Copy(saveData, temp, saveData.Length);
    9.         t.LoadRawTextureData(temp); // i think no need to apply since no gpu use
    10.         temp = t.EncodeToPNG();
    11.      
    12.         // save to disk - there will be some "empty" space at the end when you decompress
    13.         System.IO.File.WriteAllBytes(Application.dataPath + "/savegame.dat", temp);
     
    Last edited: Nov 14, 2018
    krisu likes this.
  14. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Who goes around deleting random files in their game directories, that a recipe for disaster
    Also who makes savedata that takes gigabytes.
    Neither of these scenarios seems likely to me.
     
    SparrowGS likes this.
  15. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Just don't name it .png, and don't use .jpg or lossy formats would make it about right to me.
    Not quite understand why would do all that extra operations for it instead of using binary. But its up to you.
     
  16. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
    I merely just been translating.
    But occasionally I delete temp and save files, if they grow out of control.
     
    xVergilx likes this.
  17. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Witcher 2 save system is an abomination example of how to not to do save system. At the end of the playthrough I've ended up with 1k+ save files, each of them were about 4MB. That's what I did as well. Went and deleted some of them.

    Not to mention that it also loaded ALL data of them without paging involved. (Probably including screenshots as well)

    Single list for 500+ items were lagging so hard, that it caused almost 5+ seconds to open load menu on SSD.

    So yeah, imagine if that were the images stored in the folder with .png extension. What would any user do? Without CS education behind their back ofcourse.
     
  18. You can save PNG compressed data into any file you want.
    Like Unity is able to save tar gz files into .unitypackage files. ;)

    BTW, I would not and I do not do any of these things, I save games into simple binary with my own format with version control. If you want a quick tutorial I use similar what @Jasper-Flick describes in his tutorial: https://catlikecoding.com/unity/tutorials/hex-map/part-12/
     
    xVergilx likes this.
  19. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    I try and keep my saved data as humanly readable as possible IE:
    Code (CSharp):
    1. PlayerName = "Sparrow"
    2. Funds = 1000
    I WANT that players with no proggraming knowledge what so ever be able to now only read it but understand intuitively how to modify them, you may think it makes the game "breakable" i say it add a whole lot.
    as others have probably said(havn't read all the posts) unless you save data to your own server you can't get around this problem, you can only make it hard for people that want to do that type of stuff

    this is all provided we're talking singleplayer/local multiplayer and not online matchmaking type stuff
    Isn't compressing and uncompressing a saved game image(which is super weird to me to begin with) is like super prone to data corruption?
     
  20. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    The solution I proposed is by no means the only solution but depending on what the criteria are, it can be a feasible one. I have used it before, because it made sense in that scenario. It's a while back but as far as I recall the criteria where: local save (no network connection), works on supported platforms (.net compression was not supported at the time), ease of implementation, good compression of the saved data, simple obfuscation (in my view better that binary / custom binary format as the data layout will not change). OP was asking for something simple (build in) and some obfuscation, so it might work in his/her scenario as well.

    Encryption could be added on top, but if someone puts the energy to tinker with the compressed format, they would likely also break the encryption (since they can get to the key).

    OP came across as knowledgeable enough to not use a lossy compression format, nor store GB of savegame data as PNG files, etc...
     
  21. No. PNG supports lossless data compression. (which is not true in case of JPEG files for example)
    The other possibility is just zip it. (ZLib compression) Also you don't have to call it .zip file.

    I don't use text files because parsing text is super-slow all the time. I use binary, which can be reloaded and evaluated more quickly.
     
    xrtk-build-bot likes this.
  22. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,778
    I like readability in my project. But for storing not only saves and data driven configurations, I use local data base files.

    Slow in this case is relative term.
    If we talking about 50 variables for example, this will not hurt at all.
    But if your save is 4MB size, then yes, you may need different data format.
     
  23. newlife

    newlife

    Joined:
    Jan 20, 2010
    Posts:
    1,081
    Interesting. And how you decode it to load the saved game data?
     
  24. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
  25. newlife

    newlife

    Joined:
    Jan 20, 2010
    Posts:
    1,081
  26. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    It really depends on your use case. Simple enough to just try if it suits or not... not advocating this method but it’s something I used for simplicity