Sealedkey / pfsSKKey: Difference between revisions

From PS4 Developer wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
(33 intermediate revisions by 8 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 17: Line 20:
! From !! To !! Description
! From !! To !! Description
|-
|-
| 00 || 07 || Magic ("pfsSKKey") (?playstation file system sealed key key?)
| 00 || 07 || MAGIC ("pfsSKKey") (?playstation file system sealed key key?)
|-
|-
| 08 || 0F || Version (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)
|-
|-
| 20 || 3F || Sealed Key (32 bytes)
| 20 || 3F || Encrypted key (32 bytes)
|-
|-
| 40 || 5F || SHA-256 (32 bytes)
| 40 || 5F || SHA-256 (32 bytes)
Line 30: Line 35:
'''C'''
'''C'''
<source lang="c">
<source lang="c">
  typedef struct {
  typedef struct sealedkey_t {
     const char magic;
     const unsigned char MAGIC[8];
     unsigned long version;
    const unsigned char KEYSET[2]; // short
     unsigned char iv[16];
     const unsigned char ALIGN0Bytes[6];
     unsigned char key[32];
     const unsigned char IV[16];
     unsigned char digest[32];
     const unsigned char KEY[32];
  } sealed_key;
     const unsigned char SHA256[32];
  } PfsSKKey;
</source>
</source>
'''CSharp'''
<source lang="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];
}
</source>
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 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 foreach(item, array) \
#define usb0  "/mnt/usb0/"
    for (int keep = 1, \
#define usb1  "/mnt/usb1/"
              count = 0, \
#define pfs  "decrypted_pfsSKKey.key"
              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 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))];
  unsigned char pfsSKKey[96];
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)
   
   
// Get's the encrypted sealed key based on user id.
    FILE *pfskey = fopen(toOpen, "r");  
int get_pfsSKKey(int userID)
{
  FILE *pfskey = fopen("host0:/user/home/" + userID + "/trophy/data/sce_trop/sealedkey", "r");
   
   
  if (pfskey == NULL)
    if (!pfskey) return NULL;
    return 0;
    
    
  fread(pfsSKKey, 96, 1, pfskey);
    fread(buffer, 96, 1, pfskey);
  fclose(pfskey);
    fclose(pfskey);
  return 1;
    return 1;
  }
  }
   
   
  // Dump the sealedkey. Send over tcp and save to file.
  /* Dump the sealedkey. Send over tcp and save to file */
  void dumpDecryptedSealedKey(int to)
  int dumpDecryptedSealedKey(int to) {
{
    if (to < 0 || to > 1) return -2;
  int y = get_pfsSKKey(user1);                                              // First load the key into a buffer.
  if (!y) {
    knet_printf("[-] Can not load the sealed key!\n");
    kernel.printf("[-] Can not load the sealed key!\n");
    return -1;
  }
   
   
  unsigned char decyrpted_pfsSKKey[16];
    /* First load the sealedkey into a buffer */
  int i = kernel.sceSblSsDecryptSealedKey(pfsSKKey, decrpyted_pfsSKKey);    // Now decrpyt the key.
    PfsSKKEy enc;
  knet_printf("[+] sceSblSsDecryptSealedKey returned %d\n", i);
    if (!get_pfsSKKey(&enc, USER1, tropkey)) {
  kernel.printf("[+] sceSblSsDecryptSealedKey returned %d\n", i);   
        printf("[-] Can not load the sealed key!\n");
 
        return -1;
  if (i) {                                                                 // Sending over tcp.
    }
    knet_printf("[+] Your save game key = ");
    kernel.printf("[+] Your save game key = ");
    /* 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);
   
   
    for(int x =0; x < 0x10; x++) {
        printf("\n");
    knet_printf("%02X", dec_pfsSKKey[x]);
        return 1;
    kernel.printf("%02X", dec_pfsSKKey[x]);
     }
     }
     knet_printf("\n");
     else { /* Saving to file */
    kernel.printf("\n");
        printf("[+] Will try to save to file...");
 
    if (to == 1) {                                                         // Saving to file.
      knet_printf("[+] Will try to save to file...");
      kernel.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, "w");
        FILE *dump = fopen(usb0path, "w");
   
   
      if (dump == NULL) {
        if (!dump) {
        dump = fopen(usb1path, "w");
            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 -1;
            }
          }
        }
      }
      fwrite(dec_pfsSKKey, 0x10, 1, dump);
        fwrite(&dec, 16, 1, dump);
      knet_printf("done!\n");
        printf("done!\n");
      kernel.printf("done!\n");
        fclose(dump);
      fclose(dump);
        return 1;
     }
     }
  }
  else {
    knet_printf("[+] Error!\n");
    kernel.printf("[+] Error!\n");
  }
  }
  }
</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;
     }
 }