Difference between revisions of "Talk:SELF - SPRX"

From PS3 Developer wiki
Jump to: navigation, search
Line 40: Line 40:
0x1C = 0x00002000 / 0x00020000 / 0x00040000 / 0x00080000 / 0x00116000
0x1C = 0x00002000 / 0x00020000 / 0x00040000 / 0x00080000 / 0x00116000
#define CAP_FLAG_REFTOOL 0x08
#define CAP_FLAG_DEBUG 0x10
#define CAP_FLAG_RETAIL 0x20
#define CAP_FLAG_SYSDBG 0x40
=== NPDRM Header  ===
=== NPDRM Header  ===

Revision as of 16:08, 29 December 2011

To be merged with SELF File Format and Decryption

self-capabilities flags

appldr 0x17 = 0x78 xsetting 0x17 = 0x3B

        0x1B = 0x01
        0x1D = 0x02

ps3swu 0x17 = 0x7B

        0x1B = 0x01
        0x1D = 0x11
        0x1E = 0x60

lv2 0x17 = 0x7B

        0x1B = 0x01

lv1 0x17 = 0x7B

        0x1B = 0x01

libfs 0x17 = 0x7B

        0x1B = 0x01

icolaunch0x17 = 0x3B

        0x1B = 0x01
        0x1D = 0x04

hddcopy 0x17 = 0x7B

        0x1B = 0x01
        0x1D = 0x08

flowers 0x17 = 0x3B

        0x1B = 0x01
        0x1E = 0x20

fdm_spu 0x17 = 0x38 emu_drm 0x17 = 0x3B

        0x1D = 0x02

bdj 0x0F = 0x01

        0x17 = 0x27
        0x1D = 0x02

0x0C = 0x00000001 0x14 = 0x00000038 / 0x0000003B / 0x00000078 / 0x0000007B / 0x00000027 0x18 = 0x00000001 0x1C = 0x00002000 / 0x00020000 / 0x00040000 / 0x00080000 / 0x00116000


#define CAP_FLAG_REFTOOL 0x08
#define CAP_FLAG_DEBUG 0x10
#define CAP_FLAG_RETAIL 0x20
#define CAP_FLAG_SYSDBG 0x40

NPDRM Header

typedef struct 
u32 block_type;         // this is 3(NPDRM)	
u32 block_size;         // this is 0x90(sizeof(Self_NPDRM))	
u32 unknown1;           // So far always 0	
u32 unknown2;           // So far always 0	
u32 magic;              // 0x4E504400(NPD)	
u32 unknown3;           // So far always 1	
u32 license;            // 1 Network License, 2 Local License, 3 Free	
u32 type;               // 1 Executable, 21 Update for Disc Based Game	
u8 titleid[0x30];	
u8 hash_unknown[0x10];	
u8 hash1[0x10];	
u8 hash2[0x10];	
u8 padding[0x10];	
} Self_NPDRM

Located after the Self Control Info.

App Info header:

Aligned to 0x10 bytes.

field offset type notes
authid 0x00 u64
unknown 0x08 u32
app_type 0x0c u32
  • 1 -- level 0
  • 2 -- level 1
  • 3 -- level 2
  • 4 -- application
  • 5 -- isolated SPU module
  • 6 -- secure loader
  • 8 -- NP-DRM application
app_version 0x10 u64

Appinfo offset 0x08

for some reason named vendor_id there. In geo makeself it was used as: set_u32(&(output_self_info_header.i_magic), 0x01000002); Not directly related to Authentication IDs, but seems to have many simularities with it, seems also related to SM ; LPAR's and their order suggests hierarchy/permission from high (can do everything) to low (lesser abilities).

'vendorid' count filetype
0xff000000 16 lv1.self's
0x07000001 180 iso spu self's
0x05000002 17 lv2_kernel.self's
0x02000003 45 ps2_emu self's
0x01000002 6147 CoreOs / dev_flash files

Encrypted phdr offset entry

There is one of these entries for each phdr entry in the elf file so that the ps3 knows where to decrypt the data from. (because it might also be compressed.)

field offset type notes
Encrypted Data Offset 0x00 u64
Encrypted Data Size 0x08 u64
unknown 0x10 u32 This has been 1 in all the examples I have seen.
unknown 0x14 u32 Always 0, as far as I know.
unknown 0x18 u32 Always 0, as far as I know.
unknown 0x1c u32 This is 2 for loadable segment types, and 0 for other types.

SDK Flags added

field offset type notes
Magic 0x0 u32 Must be "SCE\0"
version 0x4 u32 This must be 2 or the Self loader will abort
flags 0x8 u16
  • 0: retail type 0
  • 1: retail
  • 2: retail type 1
  • 0x8000: devkit
  • 4: unknown, games that require 3.42.
  • 7: unknown, all games that require 3.50 have that flag.
0001: FW 1.00 (app version 1.0.0)
0001: FW 3.15 (app version 3.15.0)
0001: FW 3.20 (app version 3.20.0)
0001: FW 3.21 (app version 3.21.0)
0001: FW 3.30 (app version 3.30.0)
0004: FW 3.40 (app version 3.40.0)
0004: FW 3.41 (app version 3.40.0)
0004: FW 3.42 (app version 3.40.0)
0007: FW 3.50 (app version 3.55.0)
000a: FW 3.55 (app version 3.55.0)
000d: FW 3.56 (app version 3.56.0)
0010: FW 3.60 (app version 3.60.0)
0010: FW 3.61 (app version 3.61.0)
0013: FW 3.65 (app version 3.65.0)
0013: FW 3.66 (app version 3.66.0)
0016: FW 3.70 (app version 3.70.0)
0016: FW 3.72 (app version 3.70.0)
0016: FW 3.73 (app version 3.73.0)

Region locking

SELF or SFO? http://www.ps3devwiki.com/index.php?title=File:Badregion-4.jpg

NPDRM Self algorithm

THIS DOES NOT ALLOW TO OBTAIN 3.60+ keys, nor piracy as you require the rif, act.dat and IDPS

On NPDRM self decryption all the security levels of the PS3 are involved: user space (vsh), kernel space(lv2), hypervisor( lv1) and isolated SPU (metldr + appldr)

The process start on vsh.elf...


Once the vsh detects that user is trying to start a self, it looks for the appinfo header type. If the type is 8, then the control digest element type 3 (NPD element) is located. From this NPD header the vsh gets the license type (free, local or network license).

If a free content(type 3) is detected then a generic klicense will be use for further steps (go to LV2). That klicensee is already public (see geohot npdrm_omac_key_1).

  npdrm_omac_key1  :   72F990788F9CFF745725F08E4C128387        # ps3publictools/include/oddkeys.h
  npdrm_omac_key2  :   6BA52976EFDA16EF3C339FB2971E256B        # ...
  npdrm_omac_key3  :   9B515FEACF75064981AA604D91A54E97        # ...

However if a paid content is to be loaded the vsh loads the act.dat and the rif associated to the content (if local it will locate a file with the same titleid on NPD element, if remote it will download to vsh process memory)

Then the signature is checked (last 0x28 bytes of both RIF and act.dat). The curves used are on vsh.self. It is a 3 element table, having the first curve nulled. The curve index for rif/act is 2. The curve values are negated as in the apploader and has the following structure

struct curve {
uint8_t p[0x14];
uint8_t a[0x14];
uint8_t b[0x14];
uint8_t N[0x14];
uint8_t Gx[0x14];
uint8_t Gy[0x14];

If the curve checks then vsh will process the rif:

struct rif {
uint8_t unk1[0x10];         //version, license type and user number
uint8_t titleid[0x30];      //Content ID
uint8 padding[0xC];         //Padding for randomness
uint32_t actDatIndex;       //Key index on act.dat between 0x00 and 0x7F
uint8 key[0x10];            //encrypted klicensee
uint64_t start_timestamp;   // timestamp of when the content was bought
uint64_t expire_timestamp;  // timestamp for expiration of content (PS+ for example)
uint8_t rs[0x28];
struct ACTDAT {
uint8_t unk1[0x10]; //Version, User number
uint8_t keyTable[0x800];    //Key Table
uint8_t signature[0x28];

Using the RIF_KEY it will obtain the actdatIndex:

AES_KEY rifKey;
uint8_t rif_key[0x10] = { 0xda, 0x7d, 0x4b, 0x5e, 0x49, 0x9a, 0x4f, 0x53, 0xb1, 0xc1, 0xa1, 0x4a, 0x74, 0x84, 0x44, 0x3b };
int result = AES_set_decrypt_key(rif_key, 0x80, &rifKey);
AES_decrypt(&rif->padding, &rif->padding, &rifKey);

And finally having the actDat key index the execution pass to LV2 syscall 471


Lv2 is accessed using syscall471 which haves the following syntax:

int syscall_471(uint32_t type, char* titleID, void* klicensee, uint8_t* actdat, uint8_t* rif, int32_t licenseType, uint8_t* magicVersion);

The function has different parameters depending if the content is debug, free or paid:

FREE: syscall471(npd.type, &npd.titleID, freeklicensee, NULL, NULL, npd.license, &npd);
PAID: syscall471(npd.type, &npd.titleID, NULL, &actdat.keyTable[rif.actDatIndex], &rif.key, npd.license, &npd);

The lv2 keeps a memory table with contentID and the associated key. When it receives a free content (r5 is not null) then copies the titleID and the klicensee to the table. For a paid content the rif.key is converted to the klicensee using:

AES_KEY IDPSKey, ConstKey, ActDatKey;
uint8_t constactdat[0x10] = { 0x5e, 0x06, 0xe0, 0x4f, 0xd9, 0x4a, 0x71, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
uint8_t encrConst[0x10];
uint8_t decryptedActDat[0x10];
uint8_t klicensee[0x10];
int result = AES_set_encrypt_key(&IDPSVariation, 0x80, &IDPSKey);
AES_encrypt(constactdat, &encrConst, &IDPSKey);
result = AES_set_decrypt_key(&encrConst,0x80,&ConstKey);
result = AES_set_decrypt_key(&decryptedActDat,0x80,&ActDatKey);

where CONSTACTDAT is a constant value on lv2, IDPSVaritaion appears to be IDPS (actually is the plain IDPS) (not checked but DRM_Manager_initialize (see graf_chokolo's "bible") to something with the same structure), actdat are the 0x10bytes selected by rif keyIndex, and rif is rif.key (bytes 0x50-0x5f).

Once transformed it is stored on memory table...

I haven't check further steps on vsh nor lv2 so perhaps there are further transformations on the paid case (NOT FOR THE FREE AS I HAVE DECRYPTED THOSE) so we are jumping directly to the appldr


As you can see from graf_chokolo payloads a parameter is passed on spu_args.field60. That parameter is the previously stored klicensee.

However this key must be transformed (again) even for the free case. The transformation is:

uint8_t decryptedKLicensee[0x10]
uint8_t KLicenseeDecryptKey[] = {0xf2, 0xfb, 0xca, 0x7a, 0x75, 0xb0, 0x4e, 0xdc, 0x13, 0x90, 0x63, 0x8c, 0xcd, 0xfd, 0xd1, 0xee};
AES_KEY KLicenseeKey
int result = AES_set_decrypt_key(KLicenseeDecryptKey,0x80,&KLICENSEEKEY);
EY is another key located inside the apploader and klicensee is the parameter.

Then we can finally remove the NPDRM layer using:

AES_KEY key;
uint8_t iv[0x10];
int result = AES_set_decrypt_key(&KLicenseeDecryptKey,0x80,&key);
AES_cbc_encrypt(self + self->metaoffset + 0x20, self + self->metaoffset + 0x20,0x40,&key,&iv,0);

Observe the above code in action at [1]

Once that layer is removed we proceed as normal:

  • Decrypt using AESCBC256 with the NPDRM keys to obtain the metadata keys
  • Decrypt using AESCTR128 the data sha,hmac,iv keys
  • Decrypt the data.

Source: http://www.ps3hax.net/showpost.php?p=259713&postcount=1 JuanNadie

Footnote: KLicenseeDecryptKey is located in appldr twice, e.g.


  Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
  000187C0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  000187D0  F2 FB CA 7A 75 B0 4E DC 13 90 63 8C CD FD D1 EE  òûÊzu°NÜ..cŒÍýÑî
  000187E0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  000187F0  F2 FB CA 7A 75 B0 4E DC 13 90 63 8C CD FD D1 EE  òûÊzu°NÜ..cŒÍýÑî


  Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
  00018EB0  F2 FB CA 7A 75 B0 4E DC 13 90 63 8C CD FD D1 EE  òûÊzu°NÜ..cŒÍýÑî
  00018EC0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  00018ED0  F2 FB CA 7A 75 B0 4E DC 13 90 63 8C CD FD D1 EE  òûÊzu°NÜ..cŒÍýÑî
  00018EE0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................


  Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
  00019730  F2 FB CA 7A 75 B0 4E DC 13 90 63 8C CD FD D1 EE  òûÊzu°NÜ..cŒÍýÑî
  00019740  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  00019750  F2 FB CA 7A 75 B0 4E DC 13 90 63 8C CD FD D1 EE  òûÊzu°NÜ..cŒÍýÑî
  00019760  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................


  Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
  0001F920  F2 FB CA 7A 75 B0 4E DC 13 90 63 8C CD FD D1 EE  òûÊzu°NÜ..cŒÍýÑî
  0001F930  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  0001F940  F2 FB CA 7A 75 B0 4E DC 13 90 63 8C CD FD D1 EE  òûÊzu°NÜ..cŒÍýÑî
  0001F950  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................


appldr/npdrm 0.92-3.31: rev_0x01.rar (2.39 KB)

Part 2

Thank to all of you. I hope someone is able to code a program using this info.

First of all, I want to congratulate Euss of ps3devwiki on finding the klicensee decrypt key and provide a proof of concept of the AppLoder part of the algorithm. Check http://ps3devwiki.com/index.php?title=Talk:SELF_File_Format_and_Decryption Now you have the tools to decrypt all free executable content.

Euss they key is not duplicated... there are two cases that lead to the same (similar to the keys, two cases so two repeated tables).

Some of you asked what this algorithm is for. It has several use from backing up PSN games so they can be used with/without license (some countries allow backups, but NEVER sharing copyrighted material....) or use game updates on lower firmwares (some updates are NPDRM so they could not be decrypted and downgraded). I don't know if DUPLEX used this method or if they replaced the data with debug versions as some implied...

Also, it can be use is to modify geohot's make_self_npdrm to use non static keys for encoding. I don't know if that would be enough to make a self runnable on 3.56+ firmware. However it is a step on the right direction (I think extra modifications are required). If someone knows which parts of the self is whitelisted it would be an interesting addition to the thread. Sony was publishing 3.55 after 3.56 went online so I really interested to see which part of the SELF was whitelisted.

Others asked for the keys. I can not provide them nor functional code to avoid being sued... Graf and geohot were sued for providing the keys and/or functional code.

RIF key

However, I can provide a tip on getting the RIF key.... once decrypted bytes 0x40 to 0x4F should be xx xx xx xx xx xx xx xx xx xx xx xx 00 00 00 aa where x is random and aa is a number between 0x00 and 0x7F. It is located on the VSH.elf (remember that PPC64 has 8 byte aligment). That is a plaintext attack + dictionary(vsh). You don't need the curves as you can not sign rif nor act.dat (You can only check that file is valid). And the vsh keys can be easily find... graf chokolo called IDPS as device_id_ptr.... and the CONST is very near on code execution...


RIF's act.dat index decryption key
actdatix_dec_key : DA7D4B5E499A4F53B1C1A14A7484443B
Actually in vsh.self

To <X>: That is a piracy related question. In addition you have published confidential info, which anyone who does RCE should avoid (I do not have the SDK). The answer is NO. Why?. See this code:

ret = sceNpDrmVerifyUpgradeLicense("FAKE_CONTENT_TO_DETECT_CFW");
if(ret == 0){
	print("CFW detected. Game will exit");

ret = sceNpDrmVerifyUpgradeLicense("REAL_CONTENT");
if (ret == 0) {
	int fd = openEncryptedContent("REAL_CONTENT.edat",......,keyForFile,sizeof(KeyForFile));
	if (fd > 0) {
		//Do things

First part is an example of how a developers can easily catch that modification and stop execution making it dangerous (could get a ban!!!). You modification says that the console has access to a fake content, which only CFW will have. When patching code the modification should be done only to the case you want to fix. That modification should go on the executable not on npd libraries. That way we do not patch the first verify but we will patch the second...

The second part is the real reason why it wont work... you REQUIRE the rif for opening the edat. The rif holds the klicensee for both SELF and EDAT. In fact I assume that the klicensee follows the same transformation upto the apploader. That key that you see on the command it is only used to check the HMAC on the NPD element (see geohot make_self_npdrm omac calculations)

For executable the problem is similar as when trying to run another PPU executable the program will finish and ask the vsh to run the other process which will undergo the full decryption algorithm... again you need the rif.

But.... what will happen if we decrypt the paid edat/SELF using the rif and then resign and encrypt as a free content before executing the code??? (Assuming we can sign edat)

WE CAN SIGN EXECUTABLES UPTO 3.55 THANKS TO FAIL0VERFLOW'S EPIC FAIL..... I think people do not really understands what that means...

Source: http://www.ps3hax.net/showpost.php?p=260574&postcount=8

Part 2 - responce

There is a reference for PSP's act.dat rif edat format posted here: http://www.emunewz.net/forum/archive/index.php/thread-8134.html

there may be similarities between PS3 and PSP below:

EDAT/SPRX format:
0x00: 00 50 53 50 -> .PSP
0x04: 45 44 41 54 -> EDAT
0x08: 02 00 00 00 -> Content key format (0x2000000 fixed key from npdrm / 0x2000100 version key from act.dat)
0x0C: 90 00       -> Header size
0x0E: 01 01       -> Header format (01 01 = sprx; 00 01 = edat)
0x10 - 0x40       -> Content ID
0x40              -> Hash generated from Content ID
0x50: 00 00 00 00 -> NULL
0x54: 00 00 00 00 -> NULL
0x58 - 0x70       -> Signature
0x80              -> Hash generated from signature
0x90: [Encrypted PRX (SPRX)] / [PGD (EDAT)]
RIF format:
0x00: 00 00 00 01    -> License version (shared with act.dat)
0x04: 00 00 00 02    -> File version
0x08 - 0x10           -> Account ID
0x10 - 0x40           -> Content ID
0x40                     -> Hash generated from private key
0x50                     -> Hash generated from license key
0x60: 00 00 01 1F    -> License start time
0x64: C5 16 7B D8   -> License expiration time
0x68: 00 00 00 00   -> NULL
0x6C: 00 00 00 00   -> NULL
0x70 - 0x90           -> Signature
ACT.DAT format:
0x00: 00 00 00 01    -> License version (shared with .rif)
0x04: 00 00 00 01    -> File version
0x08 - 0x10             -> Account ID
0x10 - 0x1010         -> Data hashes
0x1010 - 0x1030     -> Signature[/CODE]

A MU link contains a sample act.dat and rif file for ps3 can be found if you search for "COD:BO First Strike DLC Activation blus30591" with google.

I'm reading PSP forums, and it may possible to code an utility for cfw PS3 users, that decrypts their purchased content (A valid act.dat and rif required) if knowledge matures I see the reason that, some users lost their bought DLC because of someting not related with piracy, for example updating fw, hdd, etc. A PC utility could be written only if npdrm self contains a free license, etc...

Source: http://www.ps3hax.net/showpost.php?p=260672&postcount=9

Part 3

That link was very useful. The riff structure is very similar although the signature algorithm is different.

I have some bad news. The IDPS has been confirmed as the plain IDPS with no variations (I expected it to be user ID). That means that some step is missing in the paid algorithm. For some time, people have been able to use DLC bought by other people by changing their user ID. That means that info could be extracted on any PS3, so a value coded by IDPS (which is different on EACH console) can not be part of the algorithm. I think that the value calculated by 471 is some kind of signature to validate act.dat. It will fail on different console which explains why the act.dat is deleted every time the machine boots.

So I'm going to restudy the VSH looking for the missing part. We don't know the meaning of byte 0x810 to 0x1010 of act.dat. Previously I discarded that the act.dat contained an entry for each content as it has a fixed size but it is the only place to store keys. It is a slow process so please be patient.

Meanwhile we can improved make_self_npdrm and decrypt updates (for disc games).

By the way more info on keys:

Len: 360
SHA1: 870ce226c65325a64dae9362cf9d43665d13194b
Len: 40
SHA1: 7b365a6a821fc03b1a9a764e5e695db3599ff7bc

edit: The contents of the above:

 u8 vsh_pub_key[] = {
     0x62, 0x27, 0xb0, 0x0a, 0x02, 0x85, 0x6f, 0xb0, 0x41, 0x08, 0x87, 0x67,
     0x19, 0xe0, 0xa0, 0x18, 0x32, 0x91, 0xee, 0xb9, 0x6e, 0x73, 0x6a, 0xbf,
     0x81, 0xf7, 0x0e, 0xe9, 0x16, 0x1b, 0x0d, 0xde, 0xb0, 0x26, 0x76, 0x1a,
     0xff, 0x7b, 0xc8, 0x5b,
 u8 vsh_curves[] = {
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x03, 0x9a, 0x2e, 0xb7, 0x73, 0xfc, 0xa6, 0x1d, 0xcb,
     0x52, 0x36, 0xa4, 0x2c, 0x6f, 0x7f, 0xeb, 0x42, 0x6e, 0x5a, 0xda, 0x06,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x4a, 0x39,
     0xe8, 0x0d, 0x6f, 0x15, 0x1e, 0x24, 0x52, 0x70, 0xdd, 0xa6, 0x53, 0x11,
     0xea, 0xb7, 0x63, 0x4f, 0x69, 0x57, 0x7d, 0x0f, 0x51, 0xe3, 0x06, 0x02,
     0x71, 0x1a, 0x07, 0x05, 0x9f, 0xbc, 0xa7, 0xba, 0x92, 0xf5, 0xe3, 0x4d,
     0x6f, 0x72, 0x16, 0xf0, 0xd8, 0x28, 0xa3, 0x7d, 0x41, 0x3e, 0xf7, 0x3f,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x03, 0x59, 0x74, 0x12, 0x3c, 0xcb, 0xe7, 0xfd, 0x63,
     0xe2, 0xc3, 0x1c, 0xc4, 0x65, 0xcd, 0xe0, 0x33, 0x44, 0x61, 0xf0, 0xf4,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x4a, 0x51,
     0xc3, 0xad, 0xc1, 0x9c, 0x6b, 0xb0, 0xde, 0xd8, 0xed, 0x71, 0x3b, 0xda,
     0x9b, 0x78, 0x02, 0x70, 0x20, 0x9b, 0x1d, 0xbc, 0x84, 0x3f, 0x5e, 0x09,
     0x2a, 0x50, 0x21, 0xd3, 0xa6, 0xa7, 0xaa, 0x81, 0x4e, 0x24, 0xff, 0xed,
     0x9f, 0xbd, 0xaa, 0xdb, 0x24, 0x3c, 0x86, 0x2a, 0x53, 0xa0, 0xb5, 0x20,

edit: vsh-pub-curves.rar (367 Bytes)

I apologize for providing an incomplete solutions and I hope that me or someone else completes the info.

Source: http://www.ps3hax.net/showpost.php?p=261043&postcount=10

Part 3 - responses

I'm not sure about that... It sounds weird. People had the opportunity to use DLC from others with account sharing. I log psn with your account and the psn generates a new act and rif for me (based on my IDPS??) So maybe your work isn't incomplete.

And also, if syscall471 is used to verify act.dat, what's the purpose to call that also for free content?

Source: http://www.ps3hax.net/showpost.php?p=261065&postcount=11

Don't doubt yourself, JuanNadie! The algorithm you posted is correct. It is indeed the plain IDPS. Using your posted algorithm I was able to completely remove the NPDRM layer on an encrypted, paid SELF to get the decrypted metadata keys. I suspect the game sharing people download games while logged in to a friend's PS3. When they download the game to their friend's PS3, the NPDRM layer is added using their friend's IDPS.

Source: http://www.ps3hax.net/showpost.php?p=261140&postcount=13

I can confirm it, the algo is correct

Source: http://www.ps3hax.net/showpost.php?p=261294&postcount=15

Part 4

Did it really work? Wowww... I never tested that last step as i don't have an act.dat for my current PS3 (the other has YLOD). I released the info so somenone else could test it. I modified the first message to credit you for testing

Then we have the NDPDRM algorithm solved and a new mystery (why changing userID at xregistry.sys allows using other's act.dat and rif).

If someone has access to two consoles with act.dat he should check if values from 0x10 to 0x810 decrypts to the same. If the decrypted tables are equal them we can improve the algorithm to avoid using the IDPS, so anyone that lost their act.dat but have their rif could recover their games.

IDPS for 3.55 kmeaws is located at 0x80000000003C2EF0. You will also need a program for getting it (two LV2 peeks).

AppLoader keys are at 0x32510 (program memory address for 3.56 appLdr not file offset).There are 16 keys. Then there is another unknown key and then NPDRM keys at 0x32B70. Again 16 entries (some of them nulled). Then a copy of NPDRM keys at 0x33170. The revision value on self header is use as index for these table (the fail0verflow code tested all the values until it found zero padding). scekrit could be modified to get the private keys

And now we wait until someone has guts to release a working code.

Source: http://www.ps3hax.net/showpost.php?p=261963&postcount=21

NPDRM ps3tools


ps3tools-npdrm.tar.gz (78.56 KB)


unself2 and readself2 working. see questions about section type 3 in the readme

ps3tools-npdrm-v2.tar.gz (79.45 KB)


Based off of gitbrew's 215d8903bc86539ca1da53519e2ac10eeafc4c27
ps3tools. .git folder not included to protect senstive info about the author.
Sorry about the fucked up tabs, TAB = 4 SPACES 4 LYFE!!!
Add the files in the npdrm_keystuff folder to your ps3 keys folder. Create a
file with your console's 16 byte IDPS in the 'idps' file in your ps3 keys
folder (e.g. ~/.ps3/idps).
Copy your PS3's exdata folder containing your act.dat and rif files to your
ps3 keys dir (e.g. ~/.ps3/exdata/act.dat). Compile and have fun with your
LEGALLY purchased NPDRM games!
Also works on free games without exdata/idps.
Apologies for any existing bugs in unself. Adding these changes to
unself2 is left as an exercise for the reader.
v2 info:
Added npdrm magic to unself2 and readself2
unself2 doesn't like the metadata section with type 3 in my game.
This section looks to be some kind of linking information. Here is a snippet:
I haven't yet looked around to see if this is type of section is documented anywhere.
*fail0verflow for the orginal tools
*JuanNadie for figuring out NPDRM
*euss for his endless hours of work on the wiki
Why didn't you beat me to the punch, Team PS360? I didn't need to reverse a
single instruction! It isn't that hard...

v2 Newsitem



I checked my notes on Metadata Section Header. Value on unk2 indicates the type of data:

  • 1: the section header itself
  • 2: program data. program index indicates which program section.
  • 3: section data. program index indicates which section.

I have checked several game updates and Sony removes some of the section info (I have seen the section header removed). That data is not needed on loading game (just program header, elf header and of course the program data). The ¿lv2? creates a memory image from only the data at segment Information. It never knows the contents of the metadata section headers.

For backing up a game I think is not necessary to decrypt the data just the Self header and then modify the license type to 3 (free) reencode the NPD element resign the header with the priv and reencrypt the Self header.

I don't have info on EDATA.... yet. On EDATA the index for act.dat uses the same key what I don't know if it uses the same table




unself2 now ignores metadata sections of type 3 instead of aborting. Additional
help with any remaining bugs would be greatly appreciated.

I'm sorry if everyone got the impression that these unself/readself
modifications can, by themselves, "reactivate" your NPDRM content. These are
just the first steps in the process. To those who say this is useless because
you need act.dat and rif files: unless you can get unencrypted (debug) or
easily decrypted (free, demos) PSN content, the only way to get the unencrypted
files is by decrypting it with act.dat and the content's rif file.  There are
no "crypto fails" here, proper decryption with the true keys is the only way
forward. Using the NPDRM algo with the right keys is the only way to decrypt
unless you let GameOS do it for you and hook into GameOS to either grab
intermediate keys or dump decrypted content. Using hacks to restore the NPDRM
decryption info to jailbroken PS3s is only a partial fix. For instance, unless
you patch vsh or set the SRTC to some time in the past, some content (even
non-demos and non-trials!) expires until you log into PSN and reauthenticate.

Sorry about your "technical difficulties", Team PS360. You should L2IRC.

ps3tools-npdrm-v3.tar.gz (80.05 KB)

npdrm_keystuff.rar (705 Bytes)


the edat is completely different. The edat structure is totally different:

  • An NPD element
  • Then info for the lv2/vsh: the key index, blocksize (the SPU has a max size for reading), and decrypted/decompressed file length.
  • Then I expect some metadata for keys.
  • Then structures defining length and offset for ¿decryption? and inflating.
  • The data itself.

Source: http://www.ps3hax.net/showpost.php?p=263724&postcount=42


With the release of mallory's NPDRM-enabled ps3tools, it was remarkably simple to re-enable your legally purchased PSN titles.

Overview of steps:

 unself2 -> make_self_npdrm -> pkg.py

Tools you need:

  • ps3tools modified for NPDRM use (included)
  • make_self_npdrm from geohot's tools (included in psl1ght)
  • pkg.py (included in psl1ght)

To use the NPDRM ps3tools you need:

  • Your console's IDPS
  • Your console's exdata folder (/dev_hdd0/home/xxxxxxxx/exdata/)
  • Your PSN titles (/dev_hdd0/game/NP*)

The get_idps.pkg file can be installed on your PS3. When run, it creates a file called 'idps' on the root of an attached USB drive. Copy this idps file to your PS3KEYS folder. Make sure that your PS3KEYS folder has the appldr NPDRM keys. One pair was included in mallory's ps3tools release and more can be found at Keys Appldr FTP your PS3's exdata folder to your PS3KEYS folder (e.g. ~/.ps3/exdata). Now the NPDRM modified ps3tools have all the keys they need to decrypt PSN games.

Copy a PSN title to your computer. Run nopdrm.py with the PSN game's folder and the output package names as arguments.


  nopdrm.py NPUB90126 mgsdb.pkg

The resulting package can be installed on your PS3 and will play without any PSN licensing restrictions.

NOTE: PSN titles that use encrypted data files (*.EDAT) will likely not work. nopdrm.py outputs a warning if it detects a EDAT file in the PSN title. Work on decrypting EDAT files is underway. NOTE: All pkgs were tested with OtherOS++ MFW. Results are not guaranteed on other firmwares.

Please report any bugs to #otheros on gitbrew's IRC.


  • juan nadie
  • glevand
  • geohot
  • fail0verflow
  • gitbrew


Source: http://gitbrew.org/releases/double/


granberro I'd like to share with you my fork of failoverfl0w and geohot tools.

I have fixed some bugs on fl0w tools and added all NPDRM stuff as well as @mallory did.

What's different then?

  • unself (unself2 should not skip type 3 setction IMHO) is able to save the key/iv used to encrypt the NPDRM and patch the eboot.elf for 3.41 consoles.
  • make_self_npdrm2 is able to encrypt elfs with the key/iv extracted by unself and, theoretically being accepted by OFW>3.55

With those tools, I've been able to "downgrade" LBP2 updates 1-4 and install them on a CFW 3.41.


@JuanNadie Gracias. I've just followed your clear explanations.

EDAT Stuff

My WIP on decryting EDATs. I've found 4 likely keys used in EDAT processing inside appldr (included in unedat.c). Mostly non-working unedat


Actually an EDAT has several keys. One is in the SELF, others are at the rif and others on firmware. That an EDAT works on lower firmware only proves that the firmware has those keys.

BTW I have tricked the PS3 into decrypt an EDAT (Buzz). The procedure involves knowing how the NPD element is used (most of this is already published).

       struct {
         uint32_t magic;
         uint32_t unknown2;
         uint32_t license; /* 1 network, 2 local, 3 free */
         uint32_t type; /* 1 exec, 21 update */
         uint8_t content_id[48];
         uint8_t digest[16];
         uint8_t titlefilenameHash[16];
         uint8_t headerHash[16];
         uint64_t unknown3;
         uint64_t unknown4;
       } npdrm;



Actually as I know:

uint32_t unknown2;
/* is */
edat_version[4]; /* 1, 2 or 3 (as I know, 3.15 has version 1 & 2, >=3.40 have 1&2&3 */
/* and some more info for: */
uint32_t license; /* 0 = debug */
uint32_t type; /* 0 - just file */

and uint64_t unknown4 is:

uint8_t finalize[1]; /* 0x00 - finalized edat, 0x01 - finalized sdat, 0x80 - nonfinalized edat, 0x81 nonfinalized sdat */
uint8_t data_type[3]; /* 0x01 - compressed, 0x02 - plain txt, 0x03 - compressed plain txt, 0x05 -  compressed, 0x06 - plain txt, 0x07 - compressed plain txt, ..., [B]0x0c - edat[/B], 0x0d - compressed edat, 0x3c - sdat? */
uint8_t block_size[4]; /* default is 16 kbytes = 0x4000 */
uint8_t data_size[8]; /*decoded data size */



I haven´t fully reversed the EDAT algorithm (I’m missing bytes from 0xB0 to 0xFF) but there is enough info for a post. The explanation is for those with flag (offset 0x80-0x83) equals to 0xC which is a normal EDAT. For others values minor changes should be made. Let’s begin.

USER SPACE: (Probably incomplete (enough for decryption), most of it is guessed) On previous post I mentioned the command useds by developers to open/read an EDAT. That command has 3 parts:

  • Verify: This parts verifies the NPD element by checking that user is authorized to open the file (using the devklic). In addition it calls LV2 to create an entry in the memory (probably using syscall471) so for further steps it will use the devklic (free) or the decrypted rif key (paid) (see SELF algorithm). I’ll call this rifkey on the rest of the document.
  • Open the file: This will call kernel space. Performs several checks and creates an entry on another table.
  • Read: It also calls LV2, which will decrypt and send data back.


  • When an open request is received:
    • Read the first 0x100 bytes of the file.
    • Validates first 0xA0 bytes on EDAT. This uses appldr with the following execution (see below):
      • Single execution
      • Encrypted arguments
      • CMAC. Key: rifkey, expectedHash: data at 0xA0-0xAF
      • No Encryption erk:null,riv:null
    • Validates metadatasections. Again uses appldr:
      • Multi execution. Blocks upto 0xFC00.
      • Encrypted arguments
      • CMAC. Key: rifkey, expectedHash:data at 0x90-0x9F
      • No Encryption: erk:null, riv:null

Once the NPD is validated (We have validated header upto 0xAF and the metadatasections( which validate the data itself)) an entry on a memory table is created, the entry created by syscall471 is erased and returns. I’ll call this the EDATEncryptionDataTable. This table has 10 entries (remember the limitation of simultaneous files opened??...). Each entry has the following structure:

typedef struct {
    uint64_t fileDescriptor;
    uint64_t offset;
    uint64_t fileLen;
    uint32_t flag;
    uint32_t blockSize;
    uint8_t blockBase[0x0C];
    uint8_t devklic[0x10];
    uint8_t digest[0x10];	
}EDATEncryptionData ;
  • fileDescriptor: The file descriptor
  • offset: An additional offset to calculate the position of the metadataSection. Origin unknown. Values seen 0
  • File len: Length of the uncompressed data. Copied from EDAT offset 0x88-0x8F
  • flag: Flags required to process the data. Copied from EDAT offset 0x80-0x83. Some flags are:
    • 0x80000000: Debug
    • 0x01000000: SDAT… for those rifkey is calculated differently. Algorithm is not tested yet.
    • 0x00000004: Arguments for appldr are encrypted
    • 0x00000001: Data compressed. MetadataSection length will be 0x20 bytes.
  • blockSize: The data is stored on blocks of that length. Required for decryption. Copied from EDAT offset 0x84-0x87
  • numBlocks: Number of blocks on file. Calculated using: numBlocks = (fileLen + blockSize - 1)/blockSize
  • blockBase: Common part of the key used on decryption. First 0xC bytes of headerHash. Copied from EDAT offset 0x60-0x6B.
  • devklic: Our rif key. Copied from the entry created by syscall471. FOR SDAT it is calculated using other algorithm.
  • padding: the digest from NPD. Will be the IV. Copied from EDAT offset 0x40-0x4F.
  • When an read request is received:
    • The system determines the blocks required (E.g; read from 0x3FFF to 0x8001 will read blocks 0,1 and 2).
    • For each of the blocks:
      • Calculate the blockKey as blockBase concat blockNumber.
      • Calculate block offset: Start of NPD + offset + 0x100 + metadataSectionLen* numBlocks + blockSize*blockNumber. metadataSectionLen is 0x10 for flag 0xC (if compressed or with special hash would be 0x20).
      • Calculate erk: AESECB128Encrypt, key:rifKey, data:blockKey
      • Calculate hashKey: For 0xC is erk. (Others have an additional encryption)
      • Execute appLdr with the following parameters:
        • Single execution
        • Encrypted arguments
        • CMAC. Key: hashKey, expectedHash: metadataSection[blockIndex].hash
        • EncryptionCBC erk:erk, riv:npd.digest


As you know the appldr is used for decrypting SELFs (that part is documented on the wiki). However there is a second mode that is used for EDAT. To use that mode spu_arg.field35 is 5. For values 0 to 4 it will process a SELF and for others will return error. Graf_chokolo described the structure of spu_args for the SELF. However this changes for EDATs…

typedef struct
	uint64_t unk1;
	uint32_t hashFlags;
	uint32_t encryptionFlags;      
	uint64_t unk2;
	uint64_t len;
	uint64_t unk3;
	uint64_t stateAddress;       
	uint32_t field30;
	uint8_t  field34;       //Must be 0,1,2
	uint8_t  field35;       //Must be 0,1,2,3
	uint16_t  field36;      //Must be 0,1,2,3,4,5
	uint64_t field38;
	uint8_t hashKey[0x10];
	uint8_t riv[0x10];
	uint8_t erk[0x10];

Above I indicated several parameters for the appldr. Those parameters are controlled by hashFlag and encryptionFlag.

  • HashFlag: The hash is performed on input data not decrypted data. So if hash fails nothing is decrypted
MSB indicates how to use parameter hashKey.

        0x10000000: Indicates that hashKey is encrypted. Decrypt it with EDATKEY and RIVKEY
        0x20000000: Ignore hashKEY. USE EDATDEFAULTHASHKEY
        0x00000000: hashKey is not encrypted. Use it directly
LSB indicates the type of hash.

        0x00000001: HMACWithSHA1. Hash Len 0x14 bytes
        0x00000002: CMAC128. Hash len 0x10 (obvious)
        0x00000004: HMACWithSHA1. Hash Len 0x10 bytes (Hash is trunked)
  • EncryptionFlag:
MSB indicates how to use parameters riv and erk

        0x10000000: Indicated that erk is encrypted. Decrypt it with EDATKEY and RIVKEY. riv is copied
        0x20000000: Ignore riv and erk. Use EDATKEY and RIVKEY
        0x00000000: Use erk and riv directly
LSB indicates which encoding is used.

        0x00000001: No encryption (algorithm is memcpy)
        0x00000002: AESCBC128Decrypt is used.

When a key must be decrypted the algorithm is AESCBC128Decrypt.

Keys SHA1:

EDATKEY: 84E9FC3574EAA11A9462FFA53D5EA46B4D0003BF. Already in wiki
RIVKEY: E129F27C5103BC5CC44BCDF0A15E160D445066FF. This is top secret ;D

The multiple execution /single execution refers to the ability of appLdr to store an encrypted (and hashed) data on main memory to resume the hashing/decryption operations on next execution. That data is stored at stateAddress. Basically the functioning has several submodes. One for initialization (that decrypts erk, riv and hkey) and copies the state to main memory, another for processing data, which retrieves the state, process the data and updates the state, and finally another that receives the expected hash and validates. Another submode does all these ops on a single execution (calls the three submodes).

Summing up (for 0xC) for each block:

  • Calculate data offset: 0x100 + offset(0) + metadataSectionLen*numberOfBlocks + currentBlockNumber*blockSize
  • Generate block key: concat first 0xC byte of headerHash with current block number
  • Encrypt block key with rifKey using AESECB128Encrypt. This would be erk and hkey
  • Calculate riv. It is NPD digest field
  • Decrypt erk using AESCBC128Decrypt with EDATKEY and RIVKEY -> call result decryptionKey.
  • Using AESCBC128Decrypt decrypt data from offset to offset + blockSize( if last block calculate remaining bytes rounded up to 0x10 multiple). Key is decryptionKey iv is riv
  • Copy data to output file

Source: http://www.ps3hax.net/showthread.php?p=289101#post289101


After searching for those missing bytes I did not found any reference on code. So I zeroed them and feed the file to the PS3... The file was properly loaded and decrypted so: -Those bits are a random padding or -They are not checked ,nor required for creating an EDAT.

That means that you are able to "free" your EDATs using the method above. Remember that you're going to need the devklic and the rifkey

@Octopus For p3T you don't require the devklic cause for paid decryption you only need the key from rif... so decrypt it and use it directly like any other theme

@EXE.trim.ALL You're right on version. LV2 uses that value to check which flags are valid. However unk4 (and unk3) which are at 0x70 are zeroes. Your info is for the next 16 bytes located at 0x80. Also you separate finalize and type. From the assembly I can say that the original source code considers it a signed integer (int32_t) (that or they have a really weird compiler cause it always load that field as a word (PPC can read a single byte)).

BTW the text on flowers says something about "werewolves" and the devklic is written as an ASCII text (not binary). It was the first non free content that I decrypted on PC.

It's a pity that I would never enter on efnet (nor other sites) as long as they don't allow proxy and TOR.

actually wiki accepts proxy (and tor?)
in case you need tor for ef.net, irc.paraphysics.net accepts tor connections

Finally a bit of drama: Hotz8611, I reversed your reactPSN to see the your method and discovered that you just used the info on this post. I haven't check the vsh.self mode but I suppose that youre nullifyng the curve check and generate RAP by encrypting the rifkey (An AES and another crypto algorithm of 5 rounds with shuffle, acummulation and xoring.). I thank you for making people provide me all those RAP than I'm able to transform to rifkey but next time give proper credits (I don't know if your works is based on mallory or mine but obviously is based on info in this topic).

Source: http://www.ps3hax.net/showthread.php?p=289719#post289719


First of all, here is an implementation of the algorithm. It is not fully tested (for example with ISO.BIN.EDAT it validates but fails when decrypting) and is missing the decompression algorithm (I tried deflate but is does not work if someone identifies the algorithm please post it. Blocks start with 0x05). Also keys have been eliminated. On previous port you have the SHA1.


About compression: Instead of having metadatasections of 0x10 byes the new section is 0x20 bytes long.


struct compressMetadataSection { uint8_t hash[0x10]; uint64_t fileOffset; uint32_t len; uint32_t isEndOfCompression; }

The obtain bytes 0x10-01F xor of data is used

@jester You probably forgot to decrypt the key. The result of syscall471 must be decrypted using EDATKEY and RIVKEY.

@Octopus to make free files. - Create a memory image of the file. - Decrypt the data, so you have a memory copy of the file decrypted (for compressed no need to decompress) - Modify NPD to make if free (0x03 instead of 0x02). Recalculate hashes using devlikc (that why we need it). - Recrypt each block using the devklic as base to calculate blocks keys (wich will then be transformed again as does the appldr for that type). - Once recrypted, recalculate the hashes of the sections so they matched the new value for the encrypted data. -If compressed recalculate the offset and len on the metadatasection -Using the new metadatasection recalculate data 0x90-0x9F. -Using the new NPD header + new metadatasectionHash calculate hash and place it at 0xA0-0xAF. -Write file to disk (Remember, that file is function of filename, you must overwrite (not recommend while testing) or remember to rename it properly).


Source: http://www.ps3hax.net/showpost.php?p=299753&postcount=83


The code I posted already implements SDAT. You just need the SDATKEY. The SHA1 is ED2A015EEB1BD0CE06D0447F1A22AF4C1C401E4A

However you won't find it by bruteforce as it is coded as a series of inmediate values. If you check routine sub_5529C at graf_chokolo's dump_lv2 you'll see the routine that checks the edat/sdat header. Few lines below at address 5543C you'll see those inmediate values that are xored with the hash of the NPD to create the fake rifkey (the first 0x100 bytes of the npd are loaded starting at sp + 0x110)

About compression: We don´t know the algorithm but if we decrypt the data and modify the NPD so it looks like a debug you can use make_edata_npdrm to decompress it

Source: http://www.ps3hax.net/showpost.php?p=300371&postcount=89


First of all a new revision of the algorithm:

http://pastebin.com/E9ghYKj0 (backup: http://pastie.org/private/zanb7y2hjbk9yel71jhpq)


  • Added partial support for debug files
  • Added NPD version check (between 0 and3)
  • Added per version flags check
  • Added support for FLAG_0x20. (Untested)
  • Added support for versions 0 and 1 (ISO.BIN.EDAT). See below

When version is 0 or 1 instead of using the digest and the hash of the NPD for calculating the block key and the apploader's IV a zeroed byte array is used as base

I hope this helps your project Snowy.

@dsadsadsa I don't think I could help Kakaroto cause most of the checks are not on current code (They probably added further checking on later firmware version) and my expertise is reading assembly which I don't have. However if I can help then in any form they only need to contact me. In fact the only think that I know that is not already public is that 0x20 bytes are copied from the appldr to main memory just before setting mailbox to 7. Those bytes are at 0x890 and probably is the hash for the whitelist.

@EXE.trim.ALL There is no hash for SDAT. Those values are unknow and not checked(not confirmed). The only function as you have seen is to be xored to generate the key. To get the exacts values I'll need to check the SDK as those are generated there.

@Octopus I haven't look for the second part of the act.dat. My hyphotesis is that the second part of the file is used when debug is enabled and is common for all the consoles (will explain the COD trick). About the digest as I said there is no checked (is a hash of the original data which is unknown until the whole file is read so it can not be used as check). Geohot zeroed it on his code, An analysis of make package will obtain then (or wait until Kakaroto has the SELF fix and hope that it included the algorithm)

Source: http://www.ps3hax.net/showpost.php?p=300903&postcount=93

Sign executables for 3.73+

[21:00:58]	<Mathieulh>	selfs are a mess to generate properly because a lot of values need to be calculated from the original elf file
[21:01:11]	<Mathieulh>	the problem is right now all the public tools use hardcoded values
[21:01:19]	<Mathieulh>	that are grabbed from various self files
[21:01:21]	<Mathieulh>	but are not calculated
[21:01:34]	<Mathieulh>	well that's one of the many problems actually
[21:01:35]	<jevin> 	Mathieulh, things other than elf offsets?
[21:01:40]	<Mathieulh>	yah
[21:02:03]	<Mathieulh>	sony also did some fancy things with the compression self format
[21:02:12]	<Mathieulh>	where values are off by a certain offset etc etc
[21:02:38]	<Mathieulh>	if you want to make a proper self tool
[21:02:44]	<Mathieulh>	you first need to reverse make_fself
[21:03:06]	<jevin> 	not too hard with hexrays *cough*
[21:03:09]	<Mathieulh>	that's the initial step
[21:03:15]	<Mathieulh>	yeah it's not that hard
[21:03:29]	<Mathieulh>	then you'll figure what a big fuck up the self format really is xD
[21:05:14]	<Mathieulh>	but yeah just my self.cpp is 5 times larger than the entire source for geohot make_self/make_self_npdrm
[21:05:27]	<Mathieulh>	in terms of lines of code
[21:05:48]	<Mathieulh>	so his is missing shitloads of stuffs and only relies on hardcoded values
[21:06:06]	<jevin>	        entire headers copypasta'ed from existing selfs
[21:06:11]	<Mathieulh>	pretty much yah xD
[21:06:23]	<Mathieulh>	the ones on the tool I use are generated
[21:06:32]	<Mathieulh>	as in calculated and generated
[21:06:36]	<Mathieulh>	from the original elf
[21:06:52]	<Mathieulh>	btw unself is buggy too
[21:06:54]	<Mathieulh>	just so you know
[21:07:16]	<jevin>	        why havent you labeled the control flags? :)
[21:08:16]	<Mathieulh>	jevin I didn't feel the need to, I already know what they do anyway
[21:08:37]	<Mathieulh>	for example 0x40 is root rights, 0x20 is debugger rights and so on
[21:09:07]	<jevin>	        im guessing the self capabilities flags are offset 0x20 in the self header
[21:09:18]	<Mathieulh>	capabilities aren't in the header
[21:09:23]	<Mathieulh>	they are part of the metadata
[21:09:28]	<Mathieulh>	as in, they are encrypted and signed
[21:10:16]	<jevin>	        offset 0x10 in the section header?
[21:10:29]	<Mathieulh>	it's after the metadata keys
[21:10:33]	<jevin>	        no, they wouldnt be per section
[21:10:50]	<Mathieulh>	as in, right after them
[21:11:09]	<jevin>	        i see. so unself doesnt have enough fields in the metadata header
[21:11:35]	<jevin>	        i really should color in the hex values that are mapped to structures in unself vs ones that arent
[21:11:42]	<jevin>	        seems like it is missing a lot
[21:11:49]	<Mathieulh>	everything public is missing tons
[21:12:15]	<Mathieulh>	capabilities are optional mind you
[21:12:35]	<jevin>	        are they restrictive or permissive?
[21:13:11]	<Mathieulh>	restrictive
[21:13:16]	<Mathieulh>	(for most)
[21:42:15]	<jevin>	        Mathieulh, you said that the geohot npdrm keypair is blacklisted in 3.56
[21:42:30]	<jevin>	        i couldnt find the decrypted or encrypted metadata keypair in 3.56 files
[21:42:47]	<jevin>	        where does the blacklisting occur? is it a hash that is blacklisted?
[21:43:08]	<jevin> 	its interesting to me because we can make our own keypairs now with juan nadie's work
[21:48:45]	<Mathieulh>	<jevin> Mathieulh, you said that the geohot npdrm keypair is blacklisted in 3.56 <== not only that
[21:49:03]	<Mathieulh>	geohot stuff doesn't generate some of the npdrm specific values
[21:49:08]	<Mathieulh>	those were not checked in 3.55
[21:49:13]	<Mathieulh>	but they are checked in 3.56 now
[21:49:55]	<jevin>	        Mathieulh, gotcha
[21:50:09]	<jevin>	        is his keypair actually blacklisted somewhere though?
[21:50:10]	<Mathieulh>	there is no whitelist for npdrm
[21:50:22]	<Mathieulh>	so it's actually possible to generate valid npdrm self for 3.56+
[21:50:42]	<jevin>	        is it a check in appldr?
[21:50:43]	<Mathieulh>	that tool I made a screenshot of actually does that
[21:51:02]	<Mathieulh>	jevin yeah, it's enforced by lv1 though
[21:51:16]	<jevin>	        a hash comparison?
[21:51:27]	<Mathieulh>	yeah it's a hash
[21:51:30]	<Mathieulh>	but I won't say more
[21:51:35]	<jevin>	        ok :)
[21:51:55]	<Mathieulh>	everything you need is in the 3.56 fw :P
[21:52:16]	<jevin>	        rgr, i will poke around later
[21:52:34]	<jevin>	        the checks are unmodified in 3.60+?
[21:52:43]	<jevin>	        + new keys of course
[21:52:51]	<Mathieulh>	same checks
[21:54:53]	<Mathieulh>	jevin you won't get around crafting valid 3.56+ npdrm selfs without a proper makeself tool though
[21:57:18]	<jevin>	        would SCE make npdrm selfs work if actually signed?
[21:57:25]	<jevin>	        + crypted