Ren'Py 7.4 Save‑File Encryption: Evaluating a Shift from Opt‑In to Default
0 reputation · 08 Jan 2022, 20:22 UTC
0 reputation · 08 Jan 2022, 20:22 UTC
Goal: Assess whether Ren'Py should change the default value of config.encrypt_save_data from false to true in upcoming releases.
Constraints and uncertainties include the risk of permanent save loss if the per‑project encryption key is misplaced, potential I/O overhead on low‑end devices, and compatibility issues when collaborators toggle the setting between plaintext and encrypted saves. Additionally, the current encryption only protects confidentiality and integrity, leaving replay attacks unaddressed.
Should the engine generate and manage a project‑specific key automatically to reduce key‑loss risk? Would a configurable fallback to plaintext saves mitigate compatibility concerns? Is the performance impact acceptable for the target hardware baseline?
35275 reputation · 09 Jan 2022, 03:15 UTC
Short answer: not as a silent default flip. Encryption-by-default is only defensible if Ren'Py also ships automatic, recoverable key management and a plaintext fallback path. Without those two pieces, changing config.encrypt_save_data from false to true trades a minor tampering concern for a real risk of permanent save loss — a bad trade for most indie projects.
In Ren'Py 7.4, config.encrypt_save_data defaults to false. When enabled, save data is encrypted using a per-project key tied to the project's identity. Two properties matter for this decision:
The likely explanation for keeping the default false is that the threat model is weak for most visual novels: save editing is a single-player convenience problem, not a security boundary. The confirmed behavior is that the failure mode of encryption is catastrophic (total save loss) while the failure mode of plaintext is mild (players can edit saves). Defaults should fail safe, and here "safe" means readable saves.
Yes — this is a precondition for any default change, not an optional extra. A reasonable design derives the key deterministically from a stable project secret that is generated once at project creation, stored in a file excluded from distribution builds, and surfaced with a clear backup warning in the launcher. Deterministic derivation from a backed-up secret converts "lost key = lost saves" into "lost key = restore from backup," which is an acceptable risk profile.
Yes, and it is the cheapest of the three mitigations. The concrete problem: collaborators toggle the setting, and a save written in one mode fails to load in the other. A fallback where the loader detects a plaintext save and rewrites it encrypted (or vice versa, with a config flag) makes the setting non-destructive. You can verify current behavior in a test project:
# options.rpy
define config.encrypt_save_data = True
# Create a save in-game, then flip to False and reload.
# Observe whether the save loads, errors, or is silently skipped.If the save is skipped or errors, that confirms the compatibility hazard and the need for a migration path before any default change.
Probably yes on desktop hardware, where the overhead is negligible. The uncertainty is on low-end targets — sub-1GHz ARM devices, older Android phones, or large multi-megabyte save states — where encryption adds measurable I/O latency. This is the one claim you should not take on faith; benchmark it on your actual baseline hardware:
$ import time
$ t = time.time()
$ renpy.save("perf_test")
$ renpy.log("save took %.3fs" % (time.time() - t))Run with the flag on and off on the slowest device you support. If the delta is under ~100ms, performance is not a blocker.
false in 7.4-line releases.One caveat: exact key-derivation internals and the loader's cross-mode behavior vary by Ren'Py version, so confirm against the 7.4 source and changelog before relying on the details above.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.