Identical encryption keys generated for Ren'Py saves with the same password
0 reputation · 03 Apr 2020, 12:13 UTC
0 reputation · 03 Apr 2020, 12:13 UTC
Ren'Py allows developers to encrypt save files with a user‑supplied password to deter casual tampering. The encryption routine derives the key via PBKDF2 using a hard‑coded salt value, so every save that uses the same password produces an identical key.
This design means that if a password is reused across projects or shared between users, an attacker who obtains one encrypted save can derive the key and decrypt any other save protected with that password, weakening resistance to rainbow‑table attacks. The current implementation does not expose an option to supply a custom salt or to select an alternative key‑derivation function, leaving the community to weigh security gains against compatibility risks.
What options exist to introduce a per‑save salt without breaking already‑encrypted saves?
Is there a roadmap for exposing a configurable salt or KDF choice in a future Ren'Py release?
How can developers assess the impact of changing the salt on existing save‑file compatibility?
29775 reputation · 03 Apr 2020, 16:59 UTC
To introduce a per-save salt without breaking existing save files, you must implement a versioned encryption wrapper. Because Ren'Py's built-in password system uses a static salt, you cannot change the global salt without invalidating all current saves. Instead, you must shift the salt from a hard-coded constant to a value stored within the save file metadata itself.
The most viable path is to wrap the existing save data in a custom structure that includes a salt header. Follow these steps:
os.urandom()).There is currently no official roadmap for exposing a configurable salt or alternative KDF choices in the core Ren'Py engine. The current design prioritizes simplicity and cross-platform consistency over high-security cryptographic standards.
Changing the salt is a destructive action for any file encrypted with the previous salt. To assess the impact, you can use the following verification process:
Diagnostic Requirement: Are you using a custom Python wrapper for save handling, or are you relying exclusively on the config.save_encryption_password variable? If you are using the built-in variable, you will need to override the save/load hooks in renpy.save and renpy.load to implement the salt header described above.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.