@li0ard/widevine 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/pssh.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { pywidevine_license_protocol } from "./protos/license_protocol.js";
2
+ /** Protection System Specific Header (PSSH) object */
3
+ export declare class PSSH {
4
+ version: number;
5
+ flags: number;
6
+ system_id: Uint8Array;
7
+ kids: Uint8Array[];
8
+ init_data: Uint8Array;
9
+ /** Protection System Specific Header (PSSH) */
10
+ constructor(version: number, flags: number, system_id: Uint8Array, kids: Uint8Array[] | undefined, init_data: Uint8Array);
11
+ /** Get decoded payload (Widevine only) */
12
+ get decoded(): pywidevine_license_protocol.WidevinePsshData | null;
13
+ /** Get PSSH object from bytes */
14
+ static decode(pssh: Uint8Array): PSSH;
15
+ }
package/dist/pssh.js ADDED
@@ -0,0 +1,54 @@
1
+ import { equalBytes } from "@noble/ciphers/utils.js";
2
+ import { pywidevine_license_protocol } from "./protos/license_protocol.js";
3
+ import { WIDEVINE_SID } from "./const.js";
4
+ /** Protection System Specific Header (PSSH) object */
5
+ export class PSSH {
6
+ version;
7
+ flags;
8
+ system_id;
9
+ kids;
10
+ init_data;
11
+ /** Protection System Specific Header (PSSH) */
12
+ constructor(version, flags, system_id, kids = [], init_data) {
13
+ this.version = version;
14
+ this.flags = flags;
15
+ this.system_id = system_id;
16
+ this.kids = kids;
17
+ this.init_data = init_data;
18
+ }
19
+ /** Get decoded payload (Widevine only) */
20
+ get decoded() {
21
+ return equalBytes(this.system_id, WIDEVINE_SID) ? pywidevine_license_protocol.WidevinePsshData.deserialize(this.init_data) : null;
22
+ }
23
+ /** Get PSSH object from bytes */
24
+ static decode(pssh) {
25
+ const rdr = new DataView(pssh.buffer, pssh.byteOffset);
26
+ // const size = rdr.getUint32(offset); offset += 4;
27
+ let offset = 4;
28
+ const box_header = new TextDecoder().decode(pssh.subarray(offset, offset + 4));
29
+ offset += 4;
30
+ if (box_header !== "pssh")
31
+ throw new Error("Expecting BMFF header");
32
+ const version_and_flags = rdr.getUint32(offset);
33
+ offset += 4;
34
+ const version = (version_and_flags >> 24) & 0xff;
35
+ if (version > 1)
36
+ throw new Error("Unknown PSSH version " + version);
37
+ const system_id = pssh.slice(offset, offset + 16);
38
+ offset += 16;
39
+ const kids = [];
40
+ if (version == 1) {
41
+ let kid_count = rdr.getUint32(offset);
42
+ offset += 4;
43
+ while (kid_count > 0) {
44
+ const kid = pssh.slice(offset, offset + 16);
45
+ offset += 16;
46
+ kids.push(kid);
47
+ kid_count -= 1;
48
+ }
49
+ }
50
+ //const pssh_data_len = rdr.getUint32(offset);
51
+ offset += 4;
52
+ return new PSSH(version, version_and_flags & 0xF, system_id, kids, pssh.slice(offset));
53
+ }
54
+ }
@@ -0,0 +1,10 @@
1
+ import type { pywidevine_license_protocol } from "./protos/license_protocol.js";
2
+ import type { Key } from "./key.js";
3
+ export declare class Session {
4
+ number: number;
5
+ id: Uint8Array;
6
+ servicCertificate?: pywidevine_license_protocol.SignedDrmCertificate;
7
+ context: Map<string, Uint8Array<ArrayBufferLike>[]>;
8
+ keys: Key[];
9
+ constructor(number: number);
10
+ }
@@ -0,0 +1,12 @@
1
+ import { randomBytes } from "@noble/ciphers/utils.js";
2
+ export class Session {
3
+ number;
4
+ id;
5
+ servicCertificate;
6
+ context = new Map();
7
+ keys = [];
8
+ constructor(number) {
9
+ this.number = number;
10
+ this.id = randomBytes(16);
11
+ }
12
+ }
@@ -0,0 +1,5 @@
1
+ import { pywidevine_license_protocol } from "./protos/license_protocol.js";
2
+ import type { PublicKey, PrivateKey } from 'micro-rsa-dsa-dh/rsa.js';
3
+ export declare const parseCerificate: (certificate: Uint8Array) => pywidevine_license_protocol.DrmCertificate;
4
+ export declare const decodePrivateKey: (bytes: Uint8Array) => PrivateKey;
5
+ export declare const decodePublicKey: (bytes: Uint8Array) => PublicKey;
package/dist/utils.js ADDED
@@ -0,0 +1,33 @@
1
+ import { AsnConvert } from "@peculiar/asn1-schema";
2
+ import { pywidevine_license_protocol } from "./protos/license_protocol.js";
3
+ import { RSAPrivateKey, RSAPublicKey } from "@peculiar/asn1-rsa";
4
+ import { bytesToNumberBE } from "@noble/ciphers/utils.js";
5
+ export const parseCerificate = (certificate) => {
6
+ let signedDrmCertificate;
7
+ try {
8
+ const signedMessage = pywidevine_license_protocol.SignedMessage.deserialize(certificate);
9
+ signedDrmCertificate = pywidevine_license_protocol.SignedDrmCertificate.deserialize(signedMessage.msg);
10
+ if (signedDrmCertificate.drm_certificate.length == 0)
11
+ throw new Error("");
12
+ }
13
+ catch (e) {
14
+ signedDrmCertificate = pywidevine_license_protocol.SignedDrmCertificate.deserialize(certificate);
15
+ }
16
+ if (!signedDrmCertificate.drm_certificate)
17
+ throw new Error("Can't decode DRM certificate");
18
+ return pywidevine_license_protocol.DrmCertificate.deserialize(signedDrmCertificate.drm_certificate);
19
+ };
20
+ export const decodePrivateKey = (bytes) => {
21
+ const schema = AsnConvert.parse(bytes, RSAPrivateKey);
22
+ return {
23
+ n: bytesToNumberBE(new Uint8Array(schema.modulus)),
24
+ d: bytesToNumberBE(new Uint8Array(schema.privateExponent))
25
+ };
26
+ };
27
+ export const decodePublicKey = (bytes) => {
28
+ const schema = AsnConvert.parse(bytes, RSAPublicKey);
29
+ return {
30
+ n: bytesToNumberBE(new Uint8Array(schema.modulus)),
31
+ e: bytesToNumberBE(new Uint8Array(schema.publicExponent))
32
+ };
33
+ };
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@li0ard/widevine",
3
+ "version": "0.1.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "type": "module",
7
+ "author": "li0ard",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/li0ard/widevine.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/li0ard/widevine/issues"
14
+ },
15
+ "homepage": "https://github.com/li0ard/widevine#readme",
16
+ "description": "Widevine CDM implementation in pure TypeScript",
17
+ "license": "MIT",
18
+ "scripts": {
19
+ "build": "rm -rf dist/ && tsc --project tsconfig.build.json",
20
+ "docs": "typedoc --options .config/typedoc/config.cjs"
21
+ },
22
+ "devDependencies": {
23
+ "@types/bun": "latest",
24
+ "@types/google-protobuf": "^3.15.12",
25
+ "protoc-gen-ts": "^0.8.7",
26
+ "typedoc": "^0.28.16"
27
+ },
28
+ "peerDependencies": {
29
+ "typescript": "^5.0.0"
30
+ },
31
+ "dependencies": {
32
+ "@noble/ciphers": "^2.1.1",
33
+ "@noble/hashes": "^2.0.1",
34
+ "@peculiar/asn1-rsa": "^2.6.0",
35
+ "@peculiar/asn1-schema": "^2.6.0",
36
+ "google-protobuf": "^4.0.1",
37
+ "micro-rsa-dsa-dh": "^0.2.3"
38
+ },
39
+ "files": ["dist"],
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "keywords": ["cdm", "widevine", "google"]
44
+ }