Security, integrity and compression

What a checksum is and is not, what encryption actually protects against, and what compression is allowed to do to a save file.

Data and safety NexusForge Persistence 1.0.0 Updated

Three different questions#

QuestionWhat answers itWhat it does not do
Has this file been damaged?A SHA-256 stamp over the payload, checked on every loadIt does not prove who wrote it: anyone can compute a checksum
Did the person who wrote this know the passphrase?HMAC-SHA256 over the encrypted payloadIt does not prove when it was written, or by which machine
Can a player read or change it?AES-256 with a key derived from your passphraseIt does not keep the passphrase secret: it lives in your build

Confusing those three is how a game ends up believing a checksum protects it. The package never does: the header of a protected file stays readable so the version gate and the damage check run before anything is decrypted.

Turning protection on#

csharp
class="tok-com">// Once, during startup — before the first load or save.
Persist.Protection.SetPassphrase(class="tok-str">"the phrase only your game knows");

Persist.Save(class="tok-str">"score", 1500);                    // encrypted and authenticated from here on

Persist.Protection.ClearPassphrase();           // back to readable text

The details, exactly: AES-256-CBC for the data, HMAC-SHA256 over the IV and ciphertext to authenticate it, PBKDF2-HMAC-SHA256 with a random salt per file, and 120,000 key-derivation rounds by default (written into the file, so an older save still opens if you change the setting later).

Change one byte of a protected file and the load is refused with PK-INTEGRITY-001. A build with no passphrase reading a protected save reports PK-FORMAT-001 and says why, rather than falling back to anything.

Compression#

Saves are compressed with deflate when that genuinely makes them smaller, and the file says which happened ("payloadEncoding": "json" or "deflate"). A small save is stored as it is. Compression is applied before encryption, because compressing ciphertext achieves nothing.

csharp
Persist.Protection.Compress = false;   // if you would rather always have readable text

Next#

Something wrong on this page? Every page here describes behaviour that is checked in the repository. If a page and the package disagree, the package wins.

Report a documentation problem · Error codes · Platforms and limitations