u/wazyk

[RDR2] Stadia save format uses AES-ECB, but NOT the known PS4/Xbox key — looking for help to use my old saves on PC version
▲ 16 r/Stadia+1 crossposts

[RDR2] Stadia save format uses AES-ECB, but NOT the known PS4/Xbox key — looking for help to use my old saves on PC version

Context

I've played RDR2 through Stadia when it was available, and spent hours on it. Then, Google Stadia shut down in January 2023. Before shutdown, players could export their save files via Google Takeout (Takeout/Stadia/GAMING/GAME_SAVE/). Each save slot comes as a {game}_{id}_gamesave.zip + a companion _metadata.json file.

I thought I could manage to reuse those saves in the PC version, but still no luck.

Here are the things I've gathered with the retro-engineering skill of Claude.

For Red Dead Redemption 2, the zip contains a single file named identically to the PC save slot naming convention (e.g. SRDR30015), which strongly suggests Rockstar reused the same internal save-slot structure across platforms. Unfortunately, simply copying these files into the PC save folder does not work — the game reports "no save files are present" (confirmed independently by another user here: https://steamcommunity.com/app/1174180/discussions/0/3788128816406449519/)..)

I've been trying to reverse-engineer the Stadia save format to convert it to the PC format (which is unencrypted — RDR2 PC saves start with a plaintext UTF-16LE save name string). Posting my findings here in case someone has more context or resources than I do.

What I compared

  • PC save (SRDR30015, 673,232 bytes): unencrypted. Starts directly with a UTF-16LE save name string, e.g. (Sauvegarde automatique) L'émergence d'un souvenir (2.7%) - 04.
  • Stadia save, same slot (SRDR30015 inside the Takeout zip, 836,496 bytes): high entropy from byte 0, no readable header, no plaintext strings.

Finding 1: it's AES in ECB mode

Splitting the Stadia ciphertext into 16-byte blocks (52,280 blocks total) and counting duplicates:

1 specific 16-byte block appears 9,733 times (~18.6% of all blocks!)
Most frequent block: 6b10984872f81ed72348772a2bfd1a8

That level of exact, byte-for-byte repetition at 16-byte-aligned boundaries only happens with ECB mode encrypting long runs of identical plaintext (almost certainly zero-padding / empty inventory slots / unused array entries — a very common pattern in game save structures). Any other mode (CBC, CTR, etc.) would not produce this.

Total file size (836,496 bytes) is an exact multiple of 16, consistent with a pure block-cipher payload (possibly with a plaintext header before the encrypted region, similar to consoles).

Finding 2: the known PS4/Xbox key does NOT match

There's a known AES-256-ECB key used for RDR2 (and GTA V) on PS4/Xbox, documented here:

​

GTA5_AND_REDDEAD_KEY = b'\x16\x85\xff\xa3\x8d\x01\x0f\r\xfef\x1c\xf9\xb5W,P\r\x80&H\xdb7\xb9\xed\x0fH\xc5sB\xc0"\xf5'

I tested this key (and variants: byte-reversed, AES-128 using first/last 16 bytes) against every 16-byte-aligned offset in the Stadia file, looking for the expected decrypted header magic (RSAV / PSIN, per the PS4 tool's logic). No match anywhere.

More conclusively: since we know the most common ciphertext block almost certainly decrypts to 16 zero bytes, the correct key must satisfy AES_ECB_Encrypt(key, 0x00*16) == 6b10984872f81ed72348772a2bfd1a8.... The known PS4/Xbox key does not satisfy this:

AES-256(known_key, zeros) = 3b50a400e5d0e839579f04e57ae0b9a6   (expected: 6b10984872f81ed7...)

So: same encryption scheme (AES-256-ECB), different key (or possibly different key-derivation) on Stadia vs. PS4/Xbox.

What I'm looking for

  • Has anyone documented the Stadia-specific key, or a key-derivation scheme, for RDR2/GTA5 cloud saves?
  • Is there any chance Stadia added an additional wrapping layer (Google-side encryption on top of Rockstar's own), rather than a different Rockstar key?
  • Any pointers to a memory dump, leaked SDK, or binary from the Stadia client (even partial) that might contain the key are welcome.

Happy to share the zero-block ciphertext, full entropy analysis, or test candidate keys against the known-plaintext-block check above if it helps someone continue this.

u/wazyk — 4 days ago