PSVIMG
PSVIMG files are encrypted files generated by CMA in backing up and restoring data from the Vita. The format is documented in this tool [1].
Generating PSVIMG
When CMA is used to backup system, game, or savedata from the PSVita to a PC or PS3, the following algorithm is used:
- Using a tar-like structure, stream all of the file data into a file.
- If making a PSVMD file, use the deflate algorithm to compress.
- Generate a random nonce for the first 0x10 bytes using the RndNumber syscall.
- Generate a unique session AES256-CBC key using a secret phrase and the account id.
- Generate a SHA256 hash of the plaintext every 0x8000 bytes and insert the hash into the filestream.
- Encrypt the stream data using sceSblDmac5EncDecKeyGen with the nonce as the header and the AES256-CBC session key. This key is set through kprx_auth_sm using service 0x50001. It is then used in conjunction with encdec_w_portability to decrypt/encrypt PSVIMG blocks.
- Transmit to PC or PS3.
PSVIMG Key Derivation
The AES256-CBC session key is calculated by:
- Creating a 33 byte buffer composed of 8 byte hex binary representation of your account id followed by the 0x19 byte PSVIMG secret passphrase.
- Calculating a SHA-256 hash of buffer above.
- Decrypting the 32 byte output of the calculated SHA-256 hash with AES128-ECB (128 bit key stored in kprx_auth_sm).
- This decrypted output is the derived PSVIMG AES256-CBC key.
When you backup with CMA, the files are stored in a directory in your PC that consists of 16 character hex directory name within your backup path. That hex directory name is a representation of your account id.
ex: \Documents\PS Vita\PSAVEDATA\0123456789abcdef\ with '0123456789abcdef' being your account id.
Source code
#define NP_ACCOUNT_ID_LEN 8 #define CMA_PASSPHRASE_LEN 25 static uint8_t passphrase[CMA_PASSPHRASE_LEN] = "Sri Jayewardenepura Kotte"; { ... memcpy(seed, aid, NP_ACCOUNT_ID_LEN); memcpy(seed + NP_ACCOUNT_ID_LEN, passphrase, CMA_PASSPHRASE_LEN); ... int seed_len = (NP_ACCOUNT_ID_LEN + CMA_PASSPHRASE_LEN); sha256((uint8_t*)seed, seed_len, session_key, 0); aes_ecb_decrypt(session_key, CMA_SESSION_KEY_LEN); return session_key; }
Example
This is an example where we are going to use account id: 0123456789abcdef.
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 01 23 45 67 89 AB CD EF 53 72 69 20 4A 61 79 65 .#Eg‰«ÍïSri Jaye 00000010 77 61 72 64 65 6E 65 70 75 72 61 20 4B 6F 74 74 wardenepura Kott 00000020 65 e e
SHA-256 hash of this 32 byte buffer:
02EAAB5A00EC9D4207E8B1F53F8A2F3F91F1A73AAFDD2A81CCFEE3E83E5B101A
The decrypted hash produces the following result after decrypting with AES128-ECB:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 AC A8 2B 25 34 69 8F 3B 3B EB 21 20 69 E8 37 D3 ¬¨+%4i.;;ë! iè7Ó 00000010 9E 85 34 69 73 78 89 8D 0E D7 30 7A D1 30 31 D4 ž…4isx‰..×0zÑ01Ô
This 32 byte (256 bits) sized buffer is the PSVIMG AES256-CBC key.