0
\$\begingroup\$

How can I serialize a C# object (class, struct, etc) to a file without that file being easy to read?


Binary Formatter

First I used the Binary Formatter, which worked really well, but there were a lot of warnings about data security and many said it's a bad idea.

JSON & XML Serialization

This wouldn't work for obvious reasons, these languages are designed to be easily read and easily modified by humans, therefore it's biggest strength is also it's biggest weakness in this case.

Encrypted JSON/XML

Not sure how well this would work, and how easy it would be to tell its JSON or XML, but the main reason I couldn't use it was because I couldn't figure out an easy method or way to work it. And most posts said its extremely complicated since it's designed to be hard to decrypt.


For some reason there seem to be almost no posts on this topic, even though nearly every game records the players progress and needs to do this. What other methods are there? I don't need top level security here, just something gibberish enough to put off your average Joe trying to skip half the game.

\$\endgroup\$
2
  • \$\begingroup\$ Storing/ serialization and encrypting are two different things. You can encrypt any file (aka you can first store it as json and encrypt it afterwards) \$\endgroup\$
    – Zibelas
    Commented Feb 10 at 14:23
  • \$\begingroup\$ yeah I get that, but I'm struggling to find a suitable serializaton + encryption method \$\endgroup\$
    – Pow
    Commented Feb 10 at 14:27

1 Answer 1

0
\$\begingroup\$

Is this gibberish enough?

Hexe editor view of some binary data

This is just the JSON generated by my answer to your previous question, which I then compressed to a zip file (reducing its size by half as a bonus), and renamed so it's not so obvious that it's just a zip.

That is, I started with this text in a file called data1.save:

{
    "list": [
        {
            "rid": 1000
        },
        {
            "rid": 1001
        },
        {
            "rid": 1002
        }
    ],
    "references": {
        "version": 2,
        "RefIds": [
            {
                "rid": 1000,
                "type": {
                    "class": "MixedSerializer/ObjectA",
                    "ns": "",
                    "asm": "Assembly-CSharp"
                },
                "data": {
                    "a": "apple"
                }
            },
            {
                "rid": 1001,
                "type": {
                    "class": "MixedSerializer/ObjectB",
                    "ns": "",
                    "asm": "Assembly-CSharp"
                },
                "data": {
                    "b": 42
                }
            },
            {
                "rid": 1002,
                "type": {
                    "class": "MixedSerializer/ObjectC",
                    "ns": "",
                    "asm": "Assembly-CSharp"
                },
                "data": {
                    "c": 3.141590118408203,
                    "toggle": false
                }
            }
        ]
    }
}

So the compression does a good job of hiding the obvious/familiar structure seen above.

Someone with good knowledge of the zip format would be able to recognize its signature by peeking at the bytes, but "your average Joe" would likely already assume this is not a human-editable file and give up.

(Fun fact, MS Office docs use this trick too: if you rename a .docx Word document or .pptx PowerPoint slideshow to .zip, you can unzip it to find human-readable files and folders inside. If you never though to do that with a document, most of your players will never think to do it with a save file either)

You can make this a little bit harder by running a different compression algorithm that's not so readily built-into every PC's OS, but the general point is: compressed data is no longer very human-readable, and will probably put off the type of user you're trying to deter.

You get diminishing returns if you try to add more obfuscation than this. Even if you put in high-security grade encryption, your game necessarily has to include the encryption key to be able to read and write the save files. So if you have a computer-savvy adversary, you've handed them both the lock and the key. With enough determination, they can always extract your game's decryption routine and use it themselves to modify the data, unless you do all your saving on a server you control, so the key never touches the player's device. Maybe do that if you have real money involved, like gambling applications. But for most games you're likely to be making, it's not worth that effort.

\$\endgroup\$
7
  • \$\begingroup\$ I mean that looks fine for what I would need, but is this the result of the zip file, or the serialization? \$\endgroup\$
    – Pow
    Commented Feb 10 at 14:48
  • \$\begingroup\$ The serialization makes the human readable JSON text you saw in the screenshot in my previous answer - I've added the full text above for clarity. The gibberish comes from the compression. \$\endgroup\$
    – DMGregory
    Commented Feb 10 at 14:53
  • \$\begingroup\$ Okay, so in that case, would the best method be to use System.IO.Compression.ZipFile.CreateFromDirectory()? \$\endgroup\$
    – Pow
    Commented Feb 10 at 14:59
  • \$\begingroup\$ That's a different question, and one sufficiently far outside of game-specific coding that you can probably find it addressed on StackOverflow. Keep in mind that a judgement of "best" depends on what criteria we're using to assess the solution. If it gives your desired output on your target platforms without a massive hitch, that sounds like "good enough". \$\endgroup\$
    – DMGregory
    Commented Feb 10 at 15:01
  • \$\begingroup\$ I know, I'm asking because you must have zipped it somehow, is that what you used, or did you just do it manually? \$\endgroup\$
    – Pow
    Commented Feb 10 at 15:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .