Sealedkey / pfsSKKey

From PS4 Developer wiki
Revision as of 00:36, 7 March 2021 by CelesteBlue (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

This key can be found on different places and will be used for eg. Save Data or Trophy Data decryption and encryption.

Flags[edit | edit source]

Kind Path
Trophy /user/home/user Id/trophy/data/sce_trop/sealedkey
Save Data /user/home/user Id/title Id/save data directory/sce_sys/

Structure[edit | edit source]

- size is always 96 bytes

From To Description
00 07 MAGIC ("pfsSKKey") (?playstation file system sealed key key?)
08 09 KeySet for getSealedKeySecret (changed beyond kernel 1.73)
0A 0F Just 0x00 Bytes
10 1F IV (16 bytes)
20 3F Encrypted key (32 bytes)
40 5F SHA-256 (32 bytes)

C

 typedef struct sealedkey_t {
     const unsigned char MAGIC[8];
     const unsigned char KEYSET[2]; // short
     const unsigned char ALIGN0Bytes[6];
     const unsigned char IV[16];
     const unsigned char KEY[32];
     const unsigned char SHA256[32];
 } PfsSKKey;

CSharp

 protected internal struct sealedkey {
     internal static byte[] MAGIC = new byte[8];
     internal static short KeySet;
     internal static byte[] AlignBytes = new byte[6];
     internal static byte[] IV = new byte[16];
     internal static byte[] KEY = new byte[32];
     internal static byte[] SHA256 = new byte[32];
 }

Note: You cannot use a const byte[] definition in C#. It needs to be a static byte[].

De/En -Crypting[edit | edit source]

Can be decrypted by friendly asking the OS to do it for you. You will need kernel rights to be able to ask the PS4 for it.

 /* Decryption */ 
 #define foreach(item, array) \
     for (int keep = 1, \
              count = 0, \
              size = sizeof(array) / sizeof*(array); \
          keep && count != size; \
          keep = !keep, count++) \
         for (item = (array) + count; keep; keep = !keep)
 
 typedef unsigned char byte;              /* byte defination for c/c++ */
 byte PFSK_IDENT[8] = "pfsSKKey";
 byte VERSION[8] = "\x01\x00\x00\x00\x00\x00\x00\x00"
 const char USER1 = "10000000";
 const char usb0 = "/mnt/usb0/";
 const char usb1 = "/mnt/usb1/";
 const char pfs = "dec_pfsSK.Key";
 const char home = "/user/home/";
 const char tropkey = "/trophy/data/sce_trop/sealedkey";
 char usb_error = "[-] ERROR: Can't access usb0 nor usb1!\n[-] Will return now to caller.\n"
 char usb0path[(strlen(usb0) + strlen(pfs))];
 char usb1path[strlen(usb0path)];
 
 /* Get's the encrypted sealed key based on user id */
 int get_pfsSKKey(byte *buffer, const char *userID, char path) {
     char toOpen[(strlen(home) + strlen(userID) + strlen(path))];
 
     sprintf(toOpen, home, userID, path)
 
     FILE *pfskey = fopen(toOpen, "r"); 
 
     if (!pfskey) return NULL;
  
     fread(buffer, 96, 1, pfskey);
     fclose(pfskey);
     return 1;
 }
 
 /* Dump the sealedkey. Send over tcp and save to file */
 int dumpDecryptedSealedKey(int to) {
     if (to < 0 || to > 1) return -2;
 
     /* First load the sealedkey into a buffer */
     PfsSKKEy enc;
     if (!get_pfsSKKey(&enc, USER1, tropkey)) {
         printf("[-] Can not load the sealed key!\n");
         return -1;
     }
 
     /* Let's check the pfsSKKEy */
     if (enc->MAGIC == PFSK_IDENT && enc->CAT == VERSION) {
         printf("[+] Magic and version ok!\n[+] sk IV = ");
         foreach(byte *val, &enc->IV) printf("%02X", *val);
 
         printf("\n[+] sk KEY = ");
         foreach(byte *val, enc->KEY) printf("%02X", *val);
 
         printf("\n[+] sk Key-SHA256 = ");
         foreach(byte *val, sk->SHA256) printf("%02X", *val);
         printf("\n");
         
     }
     else return -4;
 
     /* Now decrypt it */
     byte dec[16];
 
     int i;
     if (!(i = kernel.sceSblSsDecryptSealedKey(&enc, &dec))) {
         printf("[-] Error!\n[-] sceSblSsDecryptSealedKey returned %d\n", i);
         return -1;
     }
     printf("[+] sceSblSsDecryptSealedKey returned %d\n", i);
 
     if (!to) { /* Print it out */
         printf("[+] Your decrypted sealedkey = ");
 
         foreach(byte *val, &dec) printf("%02X", *val);
 
         printf("\n");
         return 1;
     }
     else { /* Saving to file */
         printf("[+] Will try to save to file...");
	    
         sprintf(usb0path, usb0, pfs);
         sprintf(usb1path, usb1, pfs);
 
         FILE *dump = fopen(usb0path, "w");
	  
         if (!dump) {
             dump = fopen(usb1path, "w");
             if (!dump) {
                 printf("fail!\n%s", usb_error);
                 return -3;
             }
         }
 
         fwrite(&dec, 16, 1, dump);
         printf("done!\n");
         fclose(dump);
         return 1;
     }
 }