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.
Three different questions#
| Question | What answers it | What it does not do |
|---|---|---|
| Has this file been damaged? | A SHA-256 stamp over the payload, checked on every load | It 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 payload | It 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 passphrase | It 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#
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 textThe 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.
Persist.Protection.Compress = false; // if you would rather always have readable textNext#
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