added automatic .prd file unpacking into bgroupcert and zgpriv

This commit is contained in:
stratumadev 2025-11-20 21:41:31 +01:00
parent d0cc551b8d
commit 26ef04a436
3 changed files with 56 additions and 20 deletions

View file

@ -18,20 +18,44 @@ try {
const files_prd = fs.readdirSync(path.join(workingDir, 'playready'));
const bgroup_file_found = files_prd.find((f) => f === 'bgroupcert.dat');
const zgpriv_file_found = files_prd.find((f) => f === 'zgpriv.dat');
const prd_file_found = files_prd.find((f) => f.endsWith('.prd'));
try {
if (bgroup_file_found && zgpriv_file_found) {
const file_bgroup = path.join(workingDir, 'playready', bgroup_file_found);
const file_zgpriv = path.join(workingDir, 'playready', zgpriv_file_found);
const file_bgroup = path.join(workingDir, 'playready', 'bgroupcert.dat');
const file_zgpriv = path.join(workingDir, 'playready', 'zgpriv.dat');
if (bgroup_file_found && zgpriv_file_found) {
const bgroup_stats = fs.statSync(file_bgroup);
const zgpriv_stats = fs.statSync(file_zgpriv);
// Zgpriv is always 32 bytes long
if (bgroup_stats.isFile() && zgpriv_stats.isFile() && zgpriv_stats.size === 32) {
const bgroup = fs.readFileSync(file_bgroup);
const zgpriv = fs.readFileSync(file_zgpriv);
// Init Playready Client
prd_cdm = Playready.init(bgroup, zgpriv);
}
} else if ((!bgroup_file_found || !zgpriv_file_found) && prd_file_found) {
const file_prd = path.join(workingDir, 'playready', prd_file_found);
// Parse PRD file
const parsed = Playready.unpackV3PRD(fs.readFileSync(file_prd));
// Write bgroupcert.dat
fs.writeFileSync(file_bgroup, parsed.bgroupcert);
// Write zgpriv.dat
fs.writeFileSync(file_zgpriv, parsed.zgpriv);
// Delete PRD file
try {
fs.rmSync(file_prd, { recursive: true, force: true });
} catch (e) {
console.warn('Failed to delete unused .prd file.');
}
console.warn('Converted deprecated .prd file into bgroupcert.dat and zgpriv.dat.');
prd_cdm = Playready.init(parsed.bgroupcert, parsed.zgpriv);
}
} catch (e) {
console.error('Error loading Playready CDM. For more informations read the readme.');

View file

@ -53,7 +53,7 @@
"m3u8-parsed": "^2.0.0",
"mpd-parser": "^1.3.1",
"node-forge": "^1.3.1",
"node-playready": "^1.0.2",
"node-playready": "^1.0.4",
"open": "^11.0.0",
"protobufjs": "^7.5.4",
"puppeteer-real-browser": "^1.4.4",

View file

@ -48,8 +48,8 @@ importers:
specifier: ^1.3.1
version: 1.3.1
node-playready:
specifier: ^1.0.2
version: 1.0.2
specifier: ^1.0.4
version: 1.0.4
open:
specifier: ^11.0.0
version: 11.0.0
@ -1271,6 +1271,10 @@ packages:
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
engines: {node: '>= 0.8'}
http-errors@2.0.1:
resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
engines: {node: '>= 0.8'}
http-proxy-agent@7.0.2:
resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
engines: {node: '>= 14'}
@ -1488,9 +1492,9 @@ packages:
resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
engines: {node: '>= 0.6'}
mime-types@3.0.1:
resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==}
engines: {node: '>= 0.6'}
mime-types@3.0.2:
resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==}
engines: {node: '>=18'}
mimic-response@3.1.0:
resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
@ -1579,8 +1583,8 @@ packages:
node-int64@0.4.0:
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
node-playready@1.0.2:
resolution: {integrity: sha512-FJQsSXrqgv3cqDW80WW6bWy43rG745JG47XjrYa0BiqNrle9DJloARi0PKYOkK5jstIVPttUIiTWQuY8su2XqQ==}
node-playready@1.0.4:
resolution: {integrity: sha512-V9+Bf3zgGnQbm7idFs1yLzRdNPDKvsv5Pyydnvvm+wKB77Irypmh53aZ9EgfrBa+/+d5X6PbOJEBqmrtkKFjkQ==}
object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
@ -2692,7 +2696,7 @@ snapshots:
accepts@2.0.0:
dependencies:
mime-types: 3.0.1
mime-types: 3.0.2
negotiator: 1.0.0
acorn-jsx@5.3.2(acorn@8.15.0):
@ -2798,7 +2802,7 @@ snapshots:
bytes: 3.1.2
content-type: 1.0.5
debug: 4.4.3
http-errors: 2.0.0
http-errors: 2.0.1
iconv-lite: 0.6.3
on-finished: 2.4.1
qs: 6.14.0
@ -3141,9 +3145,9 @@ snapshots:
etag: 1.8.1
finalhandler: 2.1.0
fresh: 2.0.0
http-errors: 2.0.0
http-errors: 2.0.1
merge-descriptors: 2.0.0
mime-types: 3.0.1
mime-types: 3.0.2
on-finished: 2.4.1
once: 1.4.0
parseurl: 1.3.3
@ -3353,6 +3357,14 @@ snapshots:
statuses: 2.0.1
toidentifier: 1.0.1
http-errors@2.0.1:
dependencies:
depd: 2.0.0
inherits: 2.0.4
setprototypeof: 1.2.0
statuses: 2.0.2
toidentifier: 1.0.1
http-proxy-agent@7.0.2:
dependencies:
agent-base: 7.1.4
@ -3541,7 +3553,7 @@ snapshots:
mime-db@1.54.0: {}
mime-types@3.0.1:
mime-types@3.0.2:
dependencies:
mime-db: 1.54.0
@ -3614,7 +3626,7 @@ snapshots:
node-int64@0.4.0: {}
node-playready@1.0.2:
node-playready@1.0.4:
dependencies:
aes-cmac: 4.0.0
elliptic: 6.6.1
@ -3897,8 +3909,8 @@ snapshots:
escape-html: 1.0.3
etag: 1.8.1
fresh: 2.0.0
http-errors: 2.0.0
mime-types: 3.0.1
http-errors: 2.0.1
mime-types: 3.0.2
ms: 2.1.3
on-finished: 2.4.1
range-parser: 1.2.1
@ -4140,7 +4152,7 @@ snapshots:
dependencies:
content-type: 1.0.5
media-typer: 1.1.0
mime-types: 3.0.1
mime-types: 3.0.2
typed-query-selector@2.12.0: {}