Skip to main content
Phasmophobia save files use a custom encryption format combining AES-CBC encryption with PBKDF2 key derivation. This page documents the binary format and JSON structure.

File Location

Windows

%USERPROFILE%\AppData\LocalLow\Kinetic Games\Phasmophobia\SaveFile.txt
Full path:
C:\Users\[Username]\AppData\LocalLow\Kinetic Games\Phasmophobia\SaveFile.txt

Binary Format

The save file is a binary file with the following structure:
┌─────────────────────┬─────────────────────────────┐
│  Initialization     │     Encrypted JSON Data     │
│  Vector (IV)        │     (AES-CBC encrypted)     │
│  16 bytes           │     Variable length         │
└─────────────────────┴─────────────────────────────┘

Structure Breakdown

1

Bytes 0-15: Initialization Vector

Random 16-byte IV generated during encryption. Used as both the IV for AES and the salt for PBKDF2.
2

Bytes 16-end: Encrypted Data

AES-CBC encrypted JSON data with PKCS7 padding.

Encryption Algorithm

Parameters

Algorithm
string
AES (Advanced Encryption Standard)
Key Size
int
128 bits (16 bytes)
Mode
string
CBC (Cipher Block Chaining)
Padding
string
PKCS7
IV Size
int
128 bits (16 bytes)

Key Derivation (PBKDF2)

var key = new Rfc2898DeriveBytes(
    password: "t36gref9u84y7f43g",  // Hard-coded secret
    salt: iv,                       // The 16-byte IV
    iterations: 100,                 // Low iteration count
    hashAlgorithm: HashAlgorithmName.SHA1
).GetBytes(16);
Secret Key
string
"t36gref9u84y7f43g" - Hard-coded in Globals.Save_Secret
Salt
byte[]
The 16-byte IV (same value used for AES-CBC)
Iterations
int
100 iterations (relatively low for modern standards)
Hash Algorithm
string
SHA1 (deprecated but still used by the game)
The encryption uses a hard-coded secret key, making all Phasmophobia save files vulnerable to decryption by anyone with this key.

Decryption Process

1

Extract IV

Read the first 16 bytes as the Initialization Vector.
var iv = new byte[16];
Array.Copy(data, iv, 16);
2

Derive AES Key

Use PBKDF2 with the hard-coded secret and extracted IV.
using var dbytes = new Rfc2898DeriveBytes(
    "t36gref9u84y7f43g", 
    iv, 
    100, 
    HashAlgorithmName.SHA1
);
var key = dbytes.GetBytes(16);
3

Configure AES Decryptor

Set up AES with CBC mode and PKCS7 padding.
using var aes = Aes.Create();
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = key;
aes.IV = iv;
4

Decrypt Data

Decrypt bytes 16 onwards using the configured AES decryptor.
using var decryptor = aes.CreateDecryptor();
using var ms = new MemoryStream(data, 16, data.Length - 16);
using var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);
using var reader = new StreamReader(cs, Encoding.UTF8);
string json = reader.ReadToEnd();

Encryption Process

1

Generate Random IV

Create a random 16-byte IV.
byte[] iv = new byte[16];
using (var rng = RandomNumberGenerator.Create())
{
    rng.GetBytes(iv);
}
2

Derive AES Key

Use PBKDF2 with the hard-coded secret and generated IV.
var key = new Rfc2898DeriveBytes(
    "t36gref9u84y7f43g", 
    iv, 
    100, 
    HashAlgorithmName.SHA1
).GetBytes(16);
3

Encrypt JSON Data

Encrypt the JSON string using AES-CBC.
using var aes = Aes.Create();
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = key;
aes.IV = iv;

var ms = new MemoryStream();
using (var enc = aes.CreateEncryptor())
using (var cs = new CryptoStream(ms, enc, CryptoStreamMode.Write))
using (var writer = new StreamWriter(cs, Encoding.UTF8))
{
    writer.Write(jsonData);
}
byte[] encryptedData = ms.ToArray();
4

Prepend IV

Combine IV and encrypted data into final output.
byte[] result = new byte[iv.Length + encryptedData.Length];
Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
Buffer.BlockCopy(encryptedData, 0, result, iv.Length, encryptedData.Length);

JSON Structure

Once decrypted, the save file contains JSON with this general structure:
{
  "PropertyName": {
    "__type": "int",
    "value": 100
  },
  "PlayersMoney": {
    "__type": "int",
    "value": 50000
  },
  "Experience": {
    "__type": "int",
    "value": 25000
  },
  "TierTwoUnlockOwned": {
    "__type": "bool",
    "value": false
  },
  "TierThreeUnlockOwned": {
    "__type": "bool",
    "value": false
  },
  "EMFReaderInventory": {
    "__type": "int",
    "value": 10
  },
  "FlashlightInventory": {
    "__type": "int",
    "value": 5
  }
}

Property Format

Each property follows this structure:
{
  "PropertyName": {
    "__type": "<type>",
    "value": <value>
  }
}
__type
string
Data type: "int", "bool", "string", etc.
value
any
The actual value (type matches __type).

Key Properties

PlayersMoney

Player’s in-game currency (integer)

Experience

Player’s XP points (integer)

TierTwoUnlockOwned

Tier 2 items unlocked (boolean)

TierThreeUnlockOwned

Tier 3 items unlocked (boolean)

[Item]Inventory

Quantity of each item type (integer)

Example: Complete Workflow

using PhasmoDecrypt;

// 1. Read encrypted save file
string savePath = Path.Combine(
    Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
    "AppData", "LocalLow", "Kinetic Games", "Phasmophobia", "SaveFile.txt"
);
byte[] encryptedData = File.ReadAllBytes(savePath);

// 2. Decrypt to JSON
var crypter = new Crypter();
string json = crypter.Decrypt(encryptedData);

// 3. Modify JSON
EditJson.UnlockAllTier3(json);
EditJson.EditMoney(Globals.DecryptedText, 999999);
EditJson.InfinityXp(Globals.DecryptedText, 1000000);

// 4. Encrypt modified JSON
byte[] newEncryptedData = crypter.EncryptData(Globals.DecryptedText);

// 5. Save (backup original first!)
File.Copy(savePath, savePath + ".backup", true);
File.WriteAllBytes(savePath, newEncryptedData);
Always backup the original save file before modifying it. Corrupted save files cannot be recovered.

Security Considerations

The encryption key "t36gref9u84y7f43g" is hard-coded in the game, making all save files equally vulnerable.
PBKDF2 uses only 100 iterations, which is far below modern recommendations (100,000+).
SHA1 is cryptographically broken and should not be used for new applications.
Using the same IV as both the AES IV and PBKDF2 salt is unconventional but not necessarily insecure.
This encryption is designed for save file integrity, not security. It prevents casual editing but is trivial to bypass with the known secret key.

Source References

  • Encryption/Decryption: /workspace/source/Classes/Crypter.cs
  • Secret Key: /workspace/source/Classes/Globals.cs:7
  • File Handling: /workspace/source/Program.cs:88-99

Build docs developers (and LLMs) love