Sealedkey / pfsSKKey: Difference between revisions

From PS4 Developer wiki
Jump to navigation Jump to search
No edit summary
 
(21 intermediate revisions by 7 users not shown)
Line 1: Line 1:
This key can be found on different places and will be used for eg. SaveGame or Trophy Data decryption and encryption.
This key can be found on different places and will be used for eg. Save Data or Trophy Data decryption and encryption.
==== Paths ====
 
==== Flags ====
 
{| class="wikitable"
{| class="wikitable"
|-
|-
! Kind !! Path
! Kind !! Path
|-
|-
| Trophys || /user/home/[[User ID|user Id]]/trophy/data/[[sce_trop]]/sealedkey
| Trophy || /user/home/[[User ID|user Id]]/trophy/data/[[sce_trop]]/sealedkey
|-
|-
| SaveGames || /user/home/[[User ID|user Id]]/[[NP Title ID|title Id]]/[[save data directory]]/[[sce_sys]]/
| Save Data || /user/home/[[User ID|user Id]]/[[NP Title ID|title Id]]/[[save data directory]]/[[sce_sys]]/
|}
|}


== Structure ==
== Structure ==
- size always 96 bytes
 
- size is always 96 bytes


{| class="wikitable"
{| class="wikitable"
Line 19: Line 22:
| 00 || 07 || MAGIC ("pfsSKKey") (?playstation file system sealed key key?)
| 00 || 07 || MAGIC ("pfsSKKey") (?playstation file system sealed key key?)
|-
|-
| 08 || 0F || Category (game=1 or version ?)
| 08 || 09 || KeySet for getSealedKeySecret (changed beyond kernel 1.73)
|-
| 0A || 0F || Just 0x00 Bytes
|-
|-
| 10 || 1F || IV (16 bytes)
| 10 || 1F || IV (16 bytes)
Line 30: Line 35:
'''C'''
'''C'''
<source lang="c">
<source lang="c">
  typedef struct sealedkey {
  typedef struct sealedkey_t {
     const unsigned char MAGIC[8];
     const unsigned char MAGIC[8];
     const unsigned char CAT[8];
     const unsigned char KEYSET[2]; // short
    const unsigned char ALIGN0Bytes[6];
     const unsigned char IV[16];
     const unsigned char IV[16];
     const unsigned char KEY[32];
     const unsigned char KEY[32];
     const unsigned char SHA256[32];
     const unsigned char SHA256[32];
  } selaedkey;
  } PfsSKKey;
</source>
</source>


Line 43: Line 49:
  protected internal struct sealedkey {
  protected internal struct sealedkey {
     internal static byte[] MAGIC = new byte[8];
     internal static byte[] MAGIC = new byte[8];
     internal static byte[] CAT = new byte[8];
    internal static short KeySet;
     internal static byte[] AlignBytes = new byte[6];
     internal static byte[] IV = new byte[16];
     internal static byte[] IV = new byte[16];
     internal static byte[] KEY = new byte[32];
     internal static byte[] KEY = new byte[32];
Line 50: Line 57:
</source>
</source>


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


== De/En -Crypting ==
== De/En -Crypting ==
Can be decrypted by frindly asking the OS to do it for you. You will need kernel rights to be able to ask the PS4 for it.
 
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.
<source lang="c">
<source lang="c">
  /* Decryption */
  /* Decryption */  
#define USER1 10000000
#define usb0  "/mnt/usb0/"
#define usb1  "/mnt/usb1/"
#define pfs  "decrypted_pfsSKKey.key"
  #define foreach(item, array) \
  #define foreach(item, array) \
     for (int keep = 1, \
     for (int keep = 1, \
               count = 0, \
               count = 0, \
               size = sizeof(array) / sizeof(*array); \
               size = sizeof(array) / sizeof*(array); \
           keep && count != size; \
           keep && count != size; \
           keep = !keep, count++) \
           keep = !keep, count++) \
Line 70: Line 73:
   
   
  typedef unsigned char byte;              /* byte defination for c/c++ */
  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 usb_error = "[-] ERROR: Can't access usb0 nor usb1!\n[-] Will return now to caller.\n"
  char usb0path, usb1path;
  char usb0path[(strlen(usb0) + strlen(pfs))];
  byte pfsSKKey[96];
  char usb1path[strlen(usb0path)];
   
   
  /* Get's the encrypted sealed key based on user id */
  /* Get's the encrypted sealed key based on user id */
  byte get_pfsSKKey(char userID) {
  int get_pfsSKKey(byte *buffer, const char *userID, char path) {
     FILE *pfskey = fopen("/user/home/" + userID + "/trophy/data/sce_trop/sealedkey", "rb");  
    char toOpen[(strlen(home) + strlen(userID) + strlen(path))];
     if (pfskey == NULL) return 0;
    sprintf(toOpen, home, userID, path)
     FILE *pfskey = fopen(toOpen, "r");  
     if (!pfskey) return NULL;
    
    
    byte pfsSKKey[96];
     fread(buffer, 96, 1, pfskey);
     fread(pfsSKKey, 96, 1, pfskey);
     fclose(pfskey);
     fclose(pfskey);
     return pfsSKKey;
     return 1;
  }
  }
   
   
  /* Dump the sealedkey. Send over tcp and save to file */
  /* Dump the sealedkey. Send over tcp and save to file */
  int dumpDecryptedSealedKey(int to) {
  int dumpDecryptedSealedKey(int to) {
     if (to != 0 || to != 1) return -2;
     if (to < 0 || to > 1) return -2;
   
   
     byte pfsSKKey;
     /* First load the sealedkey into a buffer */
     if (sizeof((pfsSKKey = get_pfsSKKey(USER1))) != 96) {
    PfsSKKEy enc;
         knet_printf("[-] Can not load the sealed key!\n");
     if (!get_pfsSKKey(&enc, USER1, tropkey)) {
        kernel.printf("[-] Can not load the sealed key!\n");
         printf("[-] Can not load the sealed key!\n");
         return -1;
         return -1;
     }
     }
   
   
     /* Now decrpyt the key */
     /* Let's check the pfsSKKEy */
     byte decyrpted_pfsSKKey[16];
     if (enc->MAGIC == PFSK_IDENT && enc->CAT == VERSION) {
    int i = kernel.sceSblSsDecryptSealedKey(pfsSKKey, decrpyted_pfsSKKey);
        printf("[+] Magic and version ok!\n[+] sk IV = ");
    knet_printf("[+] sceSblSsDecryptSealedKey returned %d\n", i);
        foreach(byte *val, &enc->IV) printf("%02X", *val);
    kernel.printf("[+] sceSblSsDecryptSealedKey returned %d\n", i);
        printf("\n[+] sk KEY = ");
        foreach(byte *val, enc->KEY) printf("%02X", *val);
   
   
    /* Sending over tcp */
        printf("\n[+] sk Key-SHA256 = ");
    if (i) {
         foreach(byte *val, sk->SHA256) printf("%02X", *val);
         if (to == 0) {
        printf("\n");
            knet_printf("[+] Your decrypted sealedkey = ");
       
            kernel.printf("[+] Your decrypted sealedkey = ");
    }
    else return -4;
   
   
            foreach(byte *val, dec_pfsSKKey) {
    /* Now decrypt it */
                knet_printf("%02X", *val);
    byte dec[16];
        kernel.printf("%02X", *val);
            }
    int i;
            knet_printf("\n");
    if (!(i = kernel.sceSblSsDecryptSealedKey(&enc, &dec))) {
            kernel.printf("\n");
        printf("[-] Error!\n[-] sceSblSsDecryptSealedKey returned %d\n", i);
            return 1;
        return -1;
        }
    }
        else { /* Saving to file */
    printf("[+] sceSblSsDecryptSealedKey returned %d\n", i);
            knet_printf("[+] Will try to save to file...");
            kernel.printf("[+] Will try to save to file...");
    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...");
     
     
            usb0path = usb0 + pfs;
        sprintf(usb0path, usb0, pfs);
            usb1path = usb1 + pfs;
        sprintf(usb1path, usb1, pfs);
            FILE *dump = fopen(usb0path, "wb");
        FILE *dump = fopen(usb0path, "w");
   
   
            if (dump == NULL) {
        if (!dump) {
                dump = fopen(usb1path, "wb");
            dump = fopen(usb1path, "w");
                if (dump == NULL) {
            if (!dump) {
                    knet_printf("fail!\n" + usb_error);
                printf("fail!\n%s", usb_error);
                    kernel.printf("fail!\n" + usb_error);
                return -3;
                    return -3;
                }
             }
             }
            fwrite(dec_pfsSKKey, 16, 1, dump);
            knet_printf("done!\n");
            kernel.printf("done!\n");
            fclose(dump);
            return 1;
         }
         }
        fwrite(&dec, 16, 1, dump);
        printf("done!\n");
        fclose(dump);
        return 1;
     }
     }
    else {
        knet_printf("[+] Error!\n");
        kernel.printf("[+] Error!\n");
    }
    return -1;
  }
  }
</source>
</source>

Latest revision as of 00:36, 7 March 2021

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;
     }
 }