UNPKG

okova

Version:

Advanced DRM inspection toolkit

1,391 lines (1,384 loc) 330 kB
// src/lib/utils.ts var encode = (input) => new TextEncoder().encode(input); var decode = (input) => new TextDecoder().decode(input); var fromText = (data) => ({ toBase64: () => { return btoa( encode(data).reduce((s, byte) => s + String.fromCharCode(byte), "") ); }, toHex: () => { return Array.from(encode(data)).map((byte) => byte.toString(16).padStart(2, "0")).join(""); }, toBuffer: () => encode(data) }); var fromBinary = (data) => ({ toBuffer: () => { const len = data.length; const buffer = new Uint8Array(len); for (let i = 0; i < len; i++) buffer[i] = data.charCodeAt(i); return buffer; } }); var parseBase64 = (data) => Uint8Array.from(atob(data), (c) => c.charCodeAt(0)); var fromBase64 = (data) => ({ toBuffer: () => parseBase64(data), toText: () => decode(parseBase64(data)), toHex: () => fromBuffer(fromBase64(data).toBuffer()).toHex() }); var fromBuffer = (data) => ({ toBase64: () => { const binString = Array.from( data, (byte) => String.fromCodePoint(byte) ).join(""); return btoa(binString); }, toHex: () => { return Array.from(data).map((byte) => byte.toString(16).padStart(2, "0")).join(""); }, toText: () => decode(data), toBinary: () => { let binary = ""; const len = data.length; for (let i = 0; i < len; i++) binary += String.fromCharCode(data[i]); return binary; } }); var parseHex = (hex) => hex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)); var fromHex = (data) => ({ toBase64: () => { return btoa(String.fromCharCode(...parseHex(data))); }, toBuffer: () => { return new Uint8Array(parseHex(data)); }, toText: () => { return decode(new Uint8Array(parseHex(data))); } }); var parseBufferSource = (data) => { if (data instanceof Uint8Array) return data; return data instanceof ArrayBuffer ? new Uint8Array(data) : new Uint8Array(data.buffer); }; var BinaryReader = class { offset; length; rawBytes; dataView; constructor(data) { this.offset = 0; this.length = data.length; this.rawBytes = new Uint8Array(data); this.dataView = new DataView(data.buffer, data.byteOffset, data.byteLength); } readUint8() { return this.dataView.getUint8(this.offset++); } readUint16(little) { const result = this.dataView.getUint16(this.offset, little); this.offset += 2; return result; } readUint32(little) { const result = this.dataView.getUint32(this.offset, little); this.offset += 4; return result; } readBytes(size) { const result = this.rawBytes.subarray(this.offset, this.offset + size); this.offset += size; return result; } reset() { this.dataView = new DataView(this.rawBytes.buffer); this.offset = 0; } }; var compareArrays = (arr1, arr2) => { if (arr1.length !== arr2.length) return false; return Array.from(arr1).every((value, index) => value === arr2[index]); }; var bytesToString = (bytes) => { return String.fromCharCode.apply(null, Array.from(bytes)); }; var bytesToBase64 = (uint8array) => { return btoa(String.fromCharCode.apply(null, Array.from(uint8array))); }; var stringToBytes = (string) => { return Uint8Array.from(string.split("").map((x) => x.charCodeAt(0))); }; var base64ToBytes = (base64_string) => { return Uint8Array.from(atob(base64_string), (c) => c.charCodeAt(0)); }; var xorArrays = (arr1, arr2) => { return new Uint8Array(arr1.map((byte, i) => byte ^ arr2[i])); }; var getRandomBytes = (size) => { const randomBytes = new Uint8Array(size); crypto.getRandomValues(randomBytes); return randomBytes; }; // src/lib/api.ts var MessageEvent = class extends Event { messageType; message; constructor(messageType, message) { super("message"); this.messageType = messageType; this.message = message; } }; var Session = class extends EventTarget { sessionId; keyStatuses; expiration; closed; onmessage; onkeyschange; onkeystatuseschange; sessionType; keySystem; keys; #closed; constructor(sessionType = "temporary", keySystem) { super(); this.sessionId = ""; this.keyStatuses = /* @__PURE__ */ new Map(); this.expiration = NaN; this.closed = new Promise((resolve) => { this.addEventListener("closed", () => resolve("closed-by-application")); }); this.onmessage = null; this.onkeyschange = null; this.onkeystatuseschange = null; this.sessionType = sessionType; this.keySystem = keySystem; this.keys = []; const sessionId = this.keySystem.createSession(this.sessionType); if (typeof sessionId === "string") this.sessionId = sessionId; this.#closed = false; } async #validate() { if (this.#closed) throw new Error("Session closed"); if (!this.sessionId) { this.sessionId = await this.keySystem.createSession(this.sessionType); } } async load(sessionId) { this.sessionId = sessionId; this.#closed = false; return true; } async generateRequest(initDataType, initData) { await this.#validate(); const request = await this.keySystem.generateRequest( this.sessionId, parseBufferSource(initData), initDataType ); this.dispatchEvent( new MessageEvent("license-request", request) ); } async update(response) { await this.#validate(); await this.keySystem.updateSession( this.sessionId, parseBufferSource(response) ); const keys = await this.keySystem.getKeys?.(this.sessionId); if (keys) { this.keys = keys; for (const key of keys) { const id = fromHex(key.keyId).toBuffer(); this.keyStatuses.set(id, "usable"); } this.dispatchEvent(new Event("keystatuseschange")); } } async close() { this.#closed = true; this.dispatchEvent(new Event("closed")); } async remove() { this.dispatchEvent(new Event("removed")); } async waitForLicenseRequest() { return new Promise((resolve) => { this.addEventListener( "message", (e) => { const event = e; if (event.messageType === "license-request") { resolve(new Uint8Array(event.message)); } }, false ); }); } async waitForKeyStatusesChange() { if (this.keys.length) return this.keys; return new Promise((resolve) => { this.addEventListener( "keystatuseschange", () => resolve(this.keys), false ); }); } }; var requestMediaKeySystemAccess = (keySystem, supportedConfigurations) => { const supportedKeySystems = /* @__PURE__ */ new Set([ "com.widevine.alpha", "com.microsoft.playready.recommendation", "remote" ]); if (!supportedKeySystems.has(keySystem)) throw new Error("Unsupported media key system"); return { keySystem, createMediaKeys: async ({ cdm }) => { const state = { serverCertificate: null }; return { createSession: (sessionType) => { const session = new Session(sessionType, cdm); return session; }, setServerCertificate: async (serverCertificate) => { state.serverCertificate = serverCertificate; return true; }, getStatusForPolicy: async () => "usable" }; }, getConfiguration: () => supportedConfigurations[0] }; }; // src/lib/crypto/common.ts import { KEYUTIL } from "jsrsasign"; import { p256 as p2563 } from "@noble/curves/nist"; import * as utils2 from "@noble/curves/utils"; // src/lib/crypto/elgamal.ts import { p256 as p2562 } from "@noble/curves/nist"; // src/lib/crypto/ecc-key.ts import { p256 } from "@noble/curves/nist"; import * as utils from "@noble/curves/utils"; var EccKey = class _EccKey { privateKey; publicKey; constructor(privateKey, publicKey) { this.privateKey = privateKey; this.publicKey = publicKey; } static randomScalar() { const randomBytes = getRandomBytes(32); return utils.bytesToNumberBE(randomBytes) % p256.CURVE.n; } static generate() { const privateKey = _EccKey.randomScalar(); const publicKey = p256.Point.BASE.multiply(privateKey).toAffine(); return new _EccKey(privateKey, publicKey); } static construct(privateKey) { const publicKey = p256.Point.BASE.multiply(privateKey).toAffine(); return new _EccKey(privateKey, publicKey); } static from(data) { const privateBytes = data.subarray(0, 32); return _EccKey.construct(utils.bytesToNumberBE(privateBytes)); } dumps(privateOnly = false) { return privateOnly ? new Uint8Array([...this.privateBytes()]) : new Uint8Array([...this.privateBytes(), ...this.publicBytes()]); } privateBytes() { return utils.numberToBytesBE(this.privateKey, 32); } publicBytes() { return new Uint8Array([ ...utils.numberToBytesBE(this.publicKey.x, 32), ...utils.numberToBytesBE(this.publicKey.y, 32) ]); } privateSha256Digest() { return createSha256(this.publicBytes()); } publicSha256Digest() { return createSha256(this.publicBytes()); } }; // src/lib/crypto/elgamal.ts var ElGamal = class { static encrypt(affineMessagePoint, affinePublicKey) { const messagePoint = new p2562.Point( affineMessagePoint.x, affineMessagePoint.y, 1n ); const publicKey = new p2562.Point(affinePublicKey.x, affinePublicKey.y, 1n); const ephemeralKey = EccKey.randomScalar(); const point1 = p2562.Point.BASE.multiply(ephemeralKey); const sharedSecret = publicKey.multiply(ephemeralKey); const point2 = messagePoint.add(sharedSecret); return { point1: point1.toAffine(), point2: point2.toAffine() }; } static decrypt({ point1, point2 }, privateKey) { const projectivePoint1 = new p2562.Point(point1.x, point1.y, 1n); const projectivePoint2 = new p2562.Point(point2.x, point2.y, 1n); const sharedSecret = projectivePoint1.multiply(privateKey); return projectivePoint2.subtract(sharedSecret).toAffine(); } }; // src/lib/crypto/common.ts var toPKCS8 = (pkcs1pem) => { const keyobj = KEYUTIL.getKey(pkcs1pem); const pkcs8pem = KEYUTIL.getPEM(keyobj, "PKCS8PRV"); return pkcs8pem; }; var toPKCS1 = (pkcs8pem) => { const keyobj = KEYUTIL.getKey(pkcs8pem); const pkcs1pem = KEYUTIL.getPEM(keyobj, "PKCS1PRV"); return pkcs1pem; }; var parseSpkiFromCertificateKey = (publicKey) => { const publicKeyDerHex = fromBuffer(publicKey).toHex(); const keyResult = KEYUTIL.parsePublicRawRSAKeyHex(publicKeyDerHex); const key = KEYUTIL.getKey(keyResult); const pem = KEYUTIL.getPEM(key); const header = "-----BEGIN PUBLIC KEY-----"; const footer = "-----END PUBLIC KEY-----"; const body = pem.substring(header.length, pem.length - footer.length - 2); return fromBase64(body).toBuffer(); }; var importSpkiKeyForEncrypt = async (keyData) => { return crypto.subtle.importKey( "spki", keyData, { name: "RSA-OAEP", hash: "SHA-1" }, true, ["encrypt"] ); }; var importSpkiKeyForVerify = async (keyData) => { return crypto.subtle.importKey( "spki", keyData, { name: "RSA-PSS", hash: "SHA-1" }, true, ["verify"] ); }; var getRandomHex = (size = 16) => { const result = []; const hexRef = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ]; for (let n = 0; n < size; n++) result.push(hexRef[Math.floor(Math.random() * 16)]); return result.join("").toUpperCase(); }; var getRandomBytes2 = (size = 16) => { return new Uint8Array(crypto.getRandomValues(new Uint8Array(size))); }; var generateAesCbcKey = async (length = 128) => crypto.subtle.generateKey({ name: "AES-CBC", length }, true, ["encrypt"]); var importAesCbcKeyForEncrypt = async (keyData) => { return crypto.subtle.importKey("raw", keyData, "AES-CBC", false, ["encrypt"]); }; var importAesCbcKeyForDecrypt = async (keyData) => crypto.subtle.importKey("raw", keyData, { name: "AES-CBC" }, false, [ "decrypt" ]); var encryptWithAesCbc = async (data, key, iv) => { const result = await crypto.subtle.encrypt( { name: "AES-CBC", iv }, key, data ); return new Uint8Array(result); }; var decryptWithAesCbc = async (data, key, iv) => { const result = await crypto.subtle.decrypt( { name: "AES-CBC", iv }, key, data ); return new Uint8Array(result); }; var encryptWithRsaOaep = async (data, key) => { const result = await crypto.subtle.encrypt({ name: "RSA-OAEP" }, key, data); return new Uint8Array(result); }; var exportKey = (key) => crypto.subtle.exportKey("raw", key).then((value) => new Uint8Array(value)); var createHmacSha256 = async (key, data) => { const hmacKey = await crypto.subtle.importKey( "raw", key, { name: "HMAC", hash: "SHA-256" }, true, ["sign", "verify"] ); const signature = await crypto.subtle.sign("HMAC", hmacKey, data); return new Uint8Array(signature); }; var createSha256 = async (data) => { const hashBuffer = await crypto.subtle.digest("SHA-256", data); const hashArray = new Uint8Array(hashBuffer); return hashArray; }; var ecc256Verify = async (publicKey, data, signature) => { return p2563.verify(signature, await createSha256(data), publicKey); }; var ecc256Sign = async (private_key, data) => { return p2563.sign(await createSha256(data), private_key); }; var ecc256decrypt = (private_key, ciphertext) => { const decrypted = ElGamal.decrypt( { point1: { x: utils2.bytesToNumberBE(ciphertext.subarray(0, 32)), y: utils2.bytesToNumberBE(ciphertext.subarray(32, 64)) }, point2: { x: utils2.bytesToNumberBE(ciphertext.subarray(64, 96)), y: utils2.bytesToNumberBE(ciphertext.subarray(96, 128)) } }, private_key ); return utils2.numberToBytesBE(decrypted.x, 32); }; var aesEcbEncrypt = async (key, data) => { const cryptoKey = await crypto.subtle.importKey("raw", key, "AES-ECB", true, [ "encrypt", "decrypt" ]); const encryptedBuffer = await crypto.subtle.encrypt( { name: "AES-ECB" }, cryptoKey, data ); return new Uint8Array(encryptedBuffer); }; // src/lib/widevine/proto/license_protocol.pb.js import * as protobufjs from "protobufjs/minimal.js"; var $protobuf = protobufjs.default || protobufjs; var $Reader = $protobuf.Reader; var $Writer = $protobuf.Writer; var $util = $protobuf.util; var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); var LicenseType = $root.LicenseType = (() => { const valuesById = {}, values = Object.create(valuesById); values[valuesById[1] = "STREAMING"] = 1; values[valuesById[2] = "OFFLINE"] = 2; values[valuesById[3] = "AUTOMATIC"] = 3; return values; })(); var PlatformVerificationStatus = $root.PlatformVerificationStatus = (() => { const valuesById = {}, values = Object.create(valuesById); values[valuesById[0] = "PLATFORM_UNVERIFIED"] = 0; values[valuesById[1] = "PLATFORM_TAMPERED"] = 1; values[valuesById[2] = "PLATFORM_SOFTWARE_VERIFIED"] = 2; values[valuesById[3] = "PLATFORM_HARDWARE_VERIFIED"] = 3; values[valuesById[4] = "PLATFORM_NO_VERIFICATION"] = 4; values[valuesById[5] = "PLATFORM_SECURE_STORAGE_SOFTWARE_VERIFIED"] = 5; return values; })(); var LicenseIdentification = $root.LicenseIdentification = (() => { function LicenseIdentification2(p) { if (p) { for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) if (p[ks[i]] != null) this[ks[i]] = p[ks[i]]; } } LicenseIdentification2.prototype.requestId = $util.newBuffer([]); LicenseIdentification2.prototype.sessionId = $util.newBuffer([]); LicenseIdentification2.prototype.purchaseId = $util.newBuffer([]); LicenseIdentification2.prototype.type = 1; LicenseIdentification2.prototype.version = 0; LicenseIdentification2.prototype.providerSessionToken = $util.newBuffer([]); LicenseIdentification2.create = function create(properties) { return new LicenseIdentification2(properties); }; LicenseIdentification2.encode = function encode2(m, w) { if (!w) w = $Writer.create(); if (m.requestId != null && Object.hasOwnProperty.call(m, "requestId")) w.uint32(10).bytes(m.requestId); if (m.sessionId != null && Object.hasOwnProperty.call(m, "sessionId")) w.uint32(18).bytes(m.sessionId); if (m.purchaseId != null && Object.hasOwnProperty.call(m, "purchaseId")) w.uint32(26).bytes(m.purchaseId); if (m.type != null && Object.hasOwnProperty.call(m, "type")) w.uint32(32).int32(m.type); if (m.version != null && Object.hasOwnProperty.call(m, "version")) w.uint32(40).int32(m.version); if (m.providerSessionToken != null && Object.hasOwnProperty.call(m, "providerSessionToken")) w.uint32(50).bytes(m.providerSessionToken); return w; }; LicenseIdentification2.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; LicenseIdentification2.decode = function decode2(r, l) { if (!(r instanceof $Reader)) r = $Reader.create(r); var c = l === void 0 ? r.len : r.pos + l, m = new $root.LicenseIdentification(); while (r.pos < c) { var t = r.uint32(); switch (t >>> 3) { case 1: { m.requestId = r.bytes(); break; } case 2: { m.sessionId = r.bytes(); break; } case 3: { m.purchaseId = r.bytes(); break; } case 4: { m.type = r.int32(); break; } case 5: { m.version = r.int32(); break; } case 6: { m.providerSessionToken = r.bytes(); break; } default: r.skipType(t & 7); break; } } return m; }; LicenseIdentification2.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; LicenseIdentification2.fromObject = function fromObject(d) { if (d instanceof $root.LicenseIdentification) return d; var m = new $root.LicenseIdentification(); if (d.requestId != null) { if (typeof d.requestId === "string") $util.base64.decode( d.requestId, m.requestId = $util.newBuffer($util.base64.length(d.requestId)), 0 ); else if (d.requestId.length >= 0) m.requestId = d.requestId; } if (d.sessionId != null) { if (typeof d.sessionId === "string") $util.base64.decode( d.sessionId, m.sessionId = $util.newBuffer($util.base64.length(d.sessionId)), 0 ); else if (d.sessionId.length >= 0) m.sessionId = d.sessionId; } if (d.purchaseId != null) { if (typeof d.purchaseId === "string") $util.base64.decode( d.purchaseId, m.purchaseId = $util.newBuffer($util.base64.length(d.purchaseId)), 0 ); else if (d.purchaseId.length >= 0) m.purchaseId = d.purchaseId; } switch (d.type) { default: if (typeof d.type === "number") { m.type = d.type; break; } break; case "STREAMING": case 1: m.type = 1; break; case "OFFLINE": case 2: m.type = 2; break; case "AUTOMATIC": case 3: m.type = 3; break; } if (d.version != null) { m.version = d.version | 0; } if (d.providerSessionToken != null) { if (typeof d.providerSessionToken === "string") $util.base64.decode( d.providerSessionToken, m.providerSessionToken = $util.newBuffer( $util.base64.length(d.providerSessionToken) ), 0 ); else if (d.providerSessionToken.length >= 0) m.providerSessionToken = d.providerSessionToken; } return m; }; LicenseIdentification2.toObject = function toObject(m, o) { if (!o) o = {}; var d = {}; if (o.defaults) { if (o.bytes === String) d.requestId = ""; else { d.requestId = []; if (o.bytes !== Array) d.requestId = $util.newBuffer(d.requestId); } if (o.bytes === String) d.sessionId = ""; else { d.sessionId = []; if (o.bytes !== Array) d.sessionId = $util.newBuffer(d.sessionId); } if (o.bytes === String) d.purchaseId = ""; else { d.purchaseId = []; if (o.bytes !== Array) d.purchaseId = $util.newBuffer(d.purchaseId); } d.type = o.enums === String ? "STREAMING" : 1; d.version = 0; if (o.bytes === String) d.providerSessionToken = ""; else { d.providerSessionToken = []; if (o.bytes !== Array) d.providerSessionToken = $util.newBuffer(d.providerSessionToken); } } if (m.requestId != null && m.hasOwnProperty("requestId")) { d.requestId = o.bytes === String ? $util.base64.encode(m.requestId, 0, m.requestId.length) : o.bytes === Array ? Array.prototype.slice.call(m.requestId) : m.requestId; } if (m.sessionId != null && m.hasOwnProperty("sessionId")) { d.sessionId = o.bytes === String ? $util.base64.encode(m.sessionId, 0, m.sessionId.length) : o.bytes === Array ? Array.prototype.slice.call(m.sessionId) : m.sessionId; } if (m.purchaseId != null && m.hasOwnProperty("purchaseId")) { d.purchaseId = o.bytes === String ? $util.base64.encode(m.purchaseId, 0, m.purchaseId.length) : o.bytes === Array ? Array.prototype.slice.call(m.purchaseId) : m.purchaseId; } if (m.type != null && m.hasOwnProperty("type")) { d.type = o.enums === String ? $root.LicenseType[m.type] === void 0 ? m.type : $root.LicenseType[m.type] : m.type; } if (m.version != null && m.hasOwnProperty("version")) { d.version = m.version; } if (m.providerSessionToken != null && m.hasOwnProperty("providerSessionToken")) { d.providerSessionToken = o.bytes === String ? $util.base64.encode( m.providerSessionToken, 0, m.providerSessionToken.length ) : o.bytes === Array ? Array.prototype.slice.call(m.providerSessionToken) : m.providerSessionToken; } return d; }; LicenseIdentification2.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; LicenseIdentification2.getTypeUrl = function getTypeUrl(typeUrlPrefix) { if (typeUrlPrefix === void 0) { typeUrlPrefix = "type.googleapis.com"; } return typeUrlPrefix + "/LicenseIdentification"; }; return LicenseIdentification2; })(); var License = $root.License = (() => { function License2(p) { this.key = []; this.groupIds = []; if (p) { for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) if (p[ks[i]] != null) this[ks[i]] = p[ks[i]]; } } License2.prototype.id = null; License2.prototype.policy = null; License2.prototype.key = $util.emptyArray; License2.prototype.licenseStartTime = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; License2.prototype.remoteAttestationVerified = false; License2.prototype.providerClientToken = $util.newBuffer([]); License2.prototype.protectionScheme = 0; License2.prototype.srmRequirement = $util.newBuffer([]); License2.prototype.srmUpdate = $util.newBuffer([]); License2.prototype.platformVerificationStatus = 4; License2.prototype.groupIds = $util.emptyArray; License2.create = function create(properties) { return new License2(properties); }; License2.encode = function encode2(m, w) { if (!w) w = $Writer.create(); if (m.id != null && Object.hasOwnProperty.call(m, "id")) $root.LicenseIdentification.encode(m.id, w.uint32(10).fork()).ldelim(); if (m.policy != null && Object.hasOwnProperty.call(m, "policy")) $root.License.Policy.encode(m.policy, w.uint32(18).fork()).ldelim(); if (m.key != null && m.key.length) { for (var i = 0; i < m.key.length; ++i) $root.License.KeyContainer.encode( m.key[i], w.uint32(26).fork() ).ldelim(); } if (m.licenseStartTime != null && Object.hasOwnProperty.call(m, "licenseStartTime")) w.uint32(32).int64(m.licenseStartTime); if (m.remoteAttestationVerified != null && Object.hasOwnProperty.call(m, "remoteAttestationVerified")) w.uint32(40).bool(m.remoteAttestationVerified); if (m.providerClientToken != null && Object.hasOwnProperty.call(m, "providerClientToken")) w.uint32(50).bytes(m.providerClientToken); if (m.protectionScheme != null && Object.hasOwnProperty.call(m, "protectionScheme")) w.uint32(56).uint32(m.protectionScheme); if (m.srmRequirement != null && Object.hasOwnProperty.call(m, "srmRequirement")) w.uint32(66).bytes(m.srmRequirement); if (m.srmUpdate != null && Object.hasOwnProperty.call(m, "srmUpdate")) w.uint32(74).bytes(m.srmUpdate); if (m.platformVerificationStatus != null && Object.hasOwnProperty.call(m, "platformVerificationStatus")) w.uint32(80).int32(m.platformVerificationStatus); if (m.groupIds != null && m.groupIds.length) { for (var i = 0; i < m.groupIds.length; ++i) w.uint32(90).bytes(m.groupIds[i]); } return w; }; License2.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; License2.decode = function decode2(r, l) { if (!(r instanceof $Reader)) r = $Reader.create(r); var c = l === void 0 ? r.len : r.pos + l, m = new $root.License(); while (r.pos < c) { var t = r.uint32(); switch (t >>> 3) { case 1: { m.id = $root.LicenseIdentification.decode(r, r.uint32()); break; } case 2: { m.policy = $root.License.Policy.decode(r, r.uint32()); break; } case 3: { if (!(m.key && m.key.length)) m.key = []; m.key.push($root.License.KeyContainer.decode(r, r.uint32())); break; } case 4: { m.licenseStartTime = r.int64(); break; } case 5: { m.remoteAttestationVerified = r.bool(); break; } case 6: { m.providerClientToken = r.bytes(); break; } case 7: { m.protectionScheme = r.uint32(); break; } case 8: { m.srmRequirement = r.bytes(); break; } case 9: { m.srmUpdate = r.bytes(); break; } case 10: { m.platformVerificationStatus = r.int32(); break; } case 11: { if (!(m.groupIds && m.groupIds.length)) m.groupIds = []; m.groupIds.push(r.bytes()); break; } default: r.skipType(t & 7); break; } } return m; }; License2.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; License2.fromObject = function fromObject(d) { if (d instanceof $root.License) return d; var m = new $root.License(); if (d.id != null) { if (typeof d.id !== "object") throw TypeError(".License.id: object expected"); m.id = $root.LicenseIdentification.fromObject(d.id); } if (d.policy != null) { if (typeof d.policy !== "object") throw TypeError(".License.policy: object expected"); m.policy = $root.License.Policy.fromObject(d.policy); } if (d.key) { if (!Array.isArray(d.key)) throw TypeError(".License.key: array expected"); m.key = []; for (var i = 0; i < d.key.length; ++i) { if (typeof d.key[i] !== "object") throw TypeError(".License.key: object expected"); m.key[i] = $root.License.KeyContainer.fromObject(d.key[i]); } } if (d.licenseStartTime != null) { if ($util.Long) (m.licenseStartTime = $util.Long.fromValue( d.licenseStartTime )).unsigned = false; else if (typeof d.licenseStartTime === "string") m.licenseStartTime = parseInt(d.licenseStartTime, 10); else if (typeof d.licenseStartTime === "number") m.licenseStartTime = d.licenseStartTime; else if (typeof d.licenseStartTime === "object") m.licenseStartTime = new $util.LongBits( d.licenseStartTime.low >>> 0, d.licenseStartTime.high >>> 0 ).toNumber(); } if (d.remoteAttestationVerified != null) { m.remoteAttestationVerified = Boolean(d.remoteAttestationVerified); } if (d.providerClientToken != null) { if (typeof d.providerClientToken === "string") $util.base64.decode( d.providerClientToken, m.providerClientToken = $util.newBuffer( $util.base64.length(d.providerClientToken) ), 0 ); else if (d.providerClientToken.length >= 0) m.providerClientToken = d.providerClientToken; } if (d.protectionScheme != null) { m.protectionScheme = d.protectionScheme >>> 0; } if (d.srmRequirement != null) { if (typeof d.srmRequirement === "string") $util.base64.decode( d.srmRequirement, m.srmRequirement = $util.newBuffer( $util.base64.length(d.srmRequirement) ), 0 ); else if (d.srmRequirement.length >= 0) m.srmRequirement = d.srmRequirement; } if (d.srmUpdate != null) { if (typeof d.srmUpdate === "string") $util.base64.decode( d.srmUpdate, m.srmUpdate = $util.newBuffer($util.base64.length(d.srmUpdate)), 0 ); else if (d.srmUpdate.length >= 0) m.srmUpdate = d.srmUpdate; } switch (d.platformVerificationStatus) { case "PLATFORM_UNVERIFIED": case 0: m.platformVerificationStatus = 0; break; case "PLATFORM_TAMPERED": case 1: m.platformVerificationStatus = 1; break; case "PLATFORM_SOFTWARE_VERIFIED": case 2: m.platformVerificationStatus = 2; break; case "PLATFORM_HARDWARE_VERIFIED": case 3: m.platformVerificationStatus = 3; break; default: if (typeof d.platformVerificationStatus === "number") { m.platformVerificationStatus = d.platformVerificationStatus; break; } break; case "PLATFORM_NO_VERIFICATION": case 4: m.platformVerificationStatus = 4; break; case "PLATFORM_SECURE_STORAGE_SOFTWARE_VERIFIED": case 5: m.platformVerificationStatus = 5; break; } if (d.groupIds) { if (!Array.isArray(d.groupIds)) throw TypeError(".License.groupIds: array expected"); m.groupIds = []; for (var i = 0; i < d.groupIds.length; ++i) { if (typeof d.groupIds[i] === "string") $util.base64.decode( d.groupIds[i], m.groupIds[i] = $util.newBuffer( $util.base64.length(d.groupIds[i]) ), 0 ); else if (d.groupIds[i].length >= 0) m.groupIds[i] = d.groupIds[i]; } } return m; }; License2.toObject = function toObject(m, o) { if (!o) o = {}; var d = {}; if (o.arrays || o.defaults) { d.key = []; d.groupIds = []; } if (o.defaults) { d.id = null; d.policy = null; if ($util.Long) { var n = new $util.Long(0, 0, false); d.licenseStartTime = o.longs === String ? n.toString() : o.longs === Number ? n.toNumber() : n; } else d.licenseStartTime = o.longs === String ? "0" : 0; d.remoteAttestationVerified = false; if (o.bytes === String) d.providerClientToken = ""; else { d.providerClientToken = []; if (o.bytes !== Array) d.providerClientToken = $util.newBuffer(d.providerClientToken); } d.protectionScheme = 0; if (o.bytes === String) d.srmRequirement = ""; else { d.srmRequirement = []; if (o.bytes !== Array) d.srmRequirement = $util.newBuffer(d.srmRequirement); } if (o.bytes === String) d.srmUpdate = ""; else { d.srmUpdate = []; if (o.bytes !== Array) d.srmUpdate = $util.newBuffer(d.srmUpdate); } d.platformVerificationStatus = o.enums === String ? "PLATFORM_NO_VERIFICATION" : 4; } if (m.id != null && m.hasOwnProperty("id")) { d.id = $root.LicenseIdentification.toObject(m.id, o); } if (m.policy != null && m.hasOwnProperty("policy")) { d.policy = $root.License.Policy.toObject(m.policy, o); } if (m.key && m.key.length) { d.key = []; for (var j = 0; j < m.key.length; ++j) { d.key[j] = $root.License.KeyContainer.toObject(m.key[j], o); } } if (m.licenseStartTime != null && m.hasOwnProperty("licenseStartTime")) { if (typeof m.licenseStartTime === "number") d.licenseStartTime = o.longs === String ? String(m.licenseStartTime) : m.licenseStartTime; else d.licenseStartTime = o.longs === String ? $util.Long.prototype.toString.call(m.licenseStartTime) : o.longs === Number ? new $util.LongBits( m.licenseStartTime.low >>> 0, m.licenseStartTime.high >>> 0 ).toNumber() : m.licenseStartTime; } if (m.remoteAttestationVerified != null && m.hasOwnProperty("remoteAttestationVerified")) { d.remoteAttestationVerified = m.remoteAttestationVerified; } if (m.providerClientToken != null && m.hasOwnProperty("providerClientToken")) { d.providerClientToken = o.bytes === String ? $util.base64.encode( m.providerClientToken, 0, m.providerClientToken.length ) : o.bytes === Array ? Array.prototype.slice.call(m.providerClientToken) : m.providerClientToken; } if (m.protectionScheme != null && m.hasOwnProperty("protectionScheme")) { d.protectionScheme = m.protectionScheme; } if (m.srmRequirement != null && m.hasOwnProperty("srmRequirement")) { d.srmRequirement = o.bytes === String ? $util.base64.encode(m.srmRequirement, 0, m.srmRequirement.length) : o.bytes === Array ? Array.prototype.slice.call(m.srmRequirement) : m.srmRequirement; } if (m.srmUpdate != null && m.hasOwnProperty("srmUpdate")) { d.srmUpdate = o.bytes === String ? $util.base64.encode(m.srmUpdate, 0, m.srmUpdate.length) : o.bytes === Array ? Array.prototype.slice.call(m.srmUpdate) : m.srmUpdate; } if (m.platformVerificationStatus != null && m.hasOwnProperty("platformVerificationStatus")) { d.platformVerificationStatus = o.enums === String ? $root.PlatformVerificationStatus[m.platformVerificationStatus] === void 0 ? m.platformVerificationStatus : $root.PlatformVerificationStatus[m.platformVerificationStatus] : m.platformVerificationStatus; } if (m.groupIds && m.groupIds.length) { d.groupIds = []; for (var j = 0; j < m.groupIds.length; ++j) { d.groupIds[j] = o.bytes === String ? $util.base64.encode(m.groupIds[j], 0, m.groupIds[j].length) : o.bytes === Array ? Array.prototype.slice.call(m.groupIds[j]) : m.groupIds[j]; } } return d; }; License2.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; License2.getTypeUrl = function getTypeUrl(typeUrlPrefix) { if (typeUrlPrefix === void 0) { typeUrlPrefix = "type.googleapis.com"; } return typeUrlPrefix + "/License"; }; License2.Policy = function() { function Policy(p) { if (p) { for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) if (p[ks[i]] != null) this[ks[i]] = p[ks[i]]; } } Policy.prototype.canPlay = false; Policy.prototype.canPersist = false; Policy.prototype.canRenew = false; Policy.prototype.rentalDurationSeconds = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; Policy.prototype.playbackDurationSeconds = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; Policy.prototype.licenseDurationSeconds = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; Policy.prototype.renewalRecoveryDurationSeconds = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; Policy.prototype.renewalServerUrl = ""; Policy.prototype.renewalDelaySeconds = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; Policy.prototype.renewalRetryIntervalSeconds = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; Policy.prototype.renewWithUsage = false; Policy.prototype.alwaysIncludeClientId = false; Policy.prototype.playStartGracePeriodSeconds = $util.Long ? $util.Long.fromBits(0, 0, false) : 0; Policy.prototype.softEnforcePlaybackDuration = false; Policy.prototype.softEnforceRentalDuration = true; Policy.create = function create(properties) { return new Policy(properties); }; Policy.encode = function encode2(m, w) { if (!w) w = $Writer.create(); if (m.canPlay != null && Object.hasOwnProperty.call(m, "canPlay")) w.uint32(8).bool(m.canPlay); if (m.canPersist != null && Object.hasOwnProperty.call(m, "canPersist")) w.uint32(16).bool(m.canPersist); if (m.canRenew != null && Object.hasOwnProperty.call(m, "canRenew")) w.uint32(24).bool(m.canRenew); if (m.rentalDurationSeconds != null && Object.hasOwnProperty.call(m, "rentalDurationSeconds")) w.uint32(32).int64(m.rentalDurationSeconds); if (m.playbackDurationSeconds != null && Object.hasOwnProperty.call(m, "playbackDurationSeconds")) w.uint32(40).int64(m.playbackDurationSeconds); if (m.licenseDurationSeconds != null && Object.hasOwnProperty.call(m, "licenseDurationSeconds")) w.uint32(48).int64(m.licenseDurationSeconds); if (m.renewalRecoveryDurationSeconds != null && Object.hasOwnProperty.call(m, "renewalRecoveryDurationSeconds")) w.uint32(56).int64(m.renewalRecoveryDurationSeconds); if (m.renewalServerUrl != null && Object.hasOwnProperty.call(m, "renewalServerUrl")) w.uint32(66).string(m.renewalServerUrl); if (m.renewalDelaySeconds != null && Object.hasOwnProperty.call(m, "renewalDelaySeconds")) w.uint32(72).int64(m.renewalDelaySeconds); if (m.renewalRetryIntervalSeconds != null && Object.hasOwnProperty.call(m, "renewalRetryIntervalSeconds")) w.uint32(80).int64(m.renewalRetryIntervalSeconds); if (m.renewWithUsage != null && Object.hasOwnProperty.call(m, "renewWithUsage")) w.uint32(88).bool(m.renewWithUsage); if (m.alwaysIncludeClientId != null && Object.hasOwnProperty.call(m, "alwaysIncludeClientId")) w.uint32(96).bool(m.alwaysIncludeClientId); if (m.playStartGracePeriodSeconds != null && Object.hasOwnProperty.call(m, "playStartGracePeriodSeconds")) w.uint32(104).int64(m.playStartGracePeriodSeconds); if (m.softEnforcePlaybackDuration != null && Object.hasOwnProperty.call(m, "softEnforcePlaybackDuration")) w.uint32(112).bool(m.softEnforcePlaybackDuration); if (m.softEnforceRentalDuration != null && Object.hasOwnProperty.call(m, "softEnforceRentalDuration")) w.uint32(120).bool(m.softEnforceRentalDuration); return w; }; Policy.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; Policy.decode = function decode2(r, l) { if (!(r instanceof $Reader)) r = $Reader.create(r); var c = l === void 0 ? r.len : r.pos + l, m = new $root.License.Policy(); while (r.pos < c) { var t = r.uint32(); switch (t >>> 3) { case 1: { m.canPlay = r.bool(); break; } case 2: { m.canPersist = r.bool(); break; } case 3: { m.canRenew = r.bool(); break; } case 4: { m.rentalDurationSeconds = r.int64(); break; } case 5: { m.playbackDurationSeconds = r.int64(); break; } case 6: { m.licenseDurationSeconds = r.int64(); break; } case 7: { m.renewalRecoveryDurationSeconds = r.int64(); break; } case 8: { m.renewalServerUrl = r.string(); break; } case 9: { m.renewalDelaySeconds = r.int64(); break; } case 10: { m.renewalRetryIntervalSeconds = r.int64(); break; } case 11: { m.renewWithUsage = r.bool(); break; } case 12: { m.alwaysIncludeClientId = r.bool(); break; } case 13: { m.playStartGracePeriodSeconds = r.int64(); break; } case 14: { m.softEnforcePlaybackDuration = r.bool(); break; } case 15: { m.softEnforceRentalDuration = r.bool(); break; } default: r.skipType(t & 7); break; } } return m; }; Policy.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; Policy.fromObject = function fromObject(d) { if (d instanceof $root.License.Policy) return d; var m = new $root.License.Policy(); if (d.canPlay != null) { m.canPlay = Boolean(d.canPlay); } if (d.canPersist != null) { m.canPersist = Boolean(d.canPersist); } if (d.canRenew != null) { m.canRenew = Boolean(d.canRenew); } if (d.rentalDurationSeconds != null) { if ($util.Long) (m.rentalDurationSeconds = $util.Long.fromValue( d.rentalDurationSeconds )).unsigned = false; else if (typeof d.rentalDurationSeconds === "string") m.rentalDurationSeconds = parseInt(d.rentalDurationSeconds, 10); else if (typeof d.rentalDurationSeconds === "number") m.rentalDurationSeconds = d.rentalDurationSeconds; else if (typeof d.rentalDurationSeconds === "object") m.rentalDurationSeconds = new $util.LongBits( d.rentalDurationSeconds.low >>> 0, d.rentalDurationSeconds.high >>> 0 ).toNumber(); } if (d.playbackDurationSeconds != null) { if ($util.Long) (m.playbackDurationSeconds = $util.Long.fromValue( d.playbackDurationSeconds )).unsigned = false; else if (typeof d.playbackDurationSeconds === "string") m.playbackDurationSeconds = parseInt(d.playbackDurationSeconds, 10); else if (typeof d.playbackDurationSeconds === "number") m.playbackDurationSeconds = d.playbackDurationSeconds; else if (typeof d.playbackDurationSeconds === "object") m.playbackDurationSeconds = new $util.LongBits( d.playbackDurationSeconds.low >>> 0, d.playbackDurationSeconds.high >>> 0 ).toNumber(); } if (d.licenseDurationSeconds != null) { if ($util.Long) (m.licenseDurationSeconds = $util.Long.fromValue( d.licenseDurationSeconds )).unsigned = false; else if (typeof d.licenseDurationSeconds === "string") m.licenseDurationSeconds = parseInt(d.licenseDurationSeconds, 10); else if (typeof d.licenseDurationSeconds === "number") m.licenseDurationSeconds = d.licenseDurationSeconds; else if (typeof d.licenseDurationSeconds === "object") m.licenseDurationSeconds = new $util.LongBits( d.licenseDurationSeconds.low >>> 0, d.licenseDurationSeconds.high >>> 0 ).toNumber(); } if (d.renewalRecoveryDurationSeconds != null) { if ($util.Long) (m.renewalRecoveryDurationSeconds = $util.Long.fromValue( d.renewalRecoveryDurationSeconds )).unsigned = false; else if (typeof d.renewalRecoveryDurationSeconds === "string") m.renewalRecoveryDurationSeconds = parseInt( d.renewalRecoveryDurationSeconds, 10 ); else if (typeof d.renewalRecoveryDurationSeconds === "number") m.renewalRecoveryDurationSeconds = d.renewalRecoveryDurationSeconds; else if (typeof d.renewalRecoveryDurationSeconds === "object") m.renewalRecoveryDurationSeconds = new $util.LongBits( d.renewalRecoveryDurationSeconds.low >>> 0, d.renewalRecoveryDurationSeconds.high >>> 0 ).toNumber(); } if (d.renewalServerUrl != null) { m.renewalServerUrl = String(d.renewalServerUrl); } if (d.renewalDelaySeconds != null) { if ($util.Long) (m.renewalDelaySeconds = $util.Long.fromValue( d.renewalDelaySeconds )).unsigned = false; else if (typeof d.renewalDelaySeconds === "string") m.renewalDelaySeconds = parseInt(d.renewalDelaySeconds, 10); else if (typeof d.renewalDelaySeconds === "number") m.renewalDelaySeconds = d.renewalDelaySeconds; else if (typeof d.renewalDelaySeconds === "object") m.renewalDelaySeconds = new $util.LongBits( d.renewalDelaySeconds.low >>> 0, d.renewalDelaySeconds.high >>> 0 ).toNumber(); } if (d.renewalRetryIntervalSeconds != null) { if ($util.Long) (m.renewalRetryIntervalSeconds = $util.Long.fromValue( d.renewalRetryIntervalSeconds )).unsigned = false; else if (typeof d.renewalRetryIntervalSeconds === "string") m.renewalRetryIntervalSeconds = parseInt( d.renewalRetryIntervalSeconds, 10 ); else if (typeof d.renewalRetryIntervalSeconds === "number") m.renewalRetryIntervalSeconds = d.renewalRetryIntervalSeconds; else if (typeof d.renewalRetryIntervalSeconds === "object") m.renewalRetryIntervalSeconds = new $util.LongBits( d.renewalRetryIntervalSeconds.low >>> 0, d.renewalRetryIntervalSeconds.high >>> 0 ).toNumber(); } if (d.renewWithUsage != null) { m.renewWithUsage = Boolean(d.renewWithUsage); } if (d.alwaysIncludeClientId != null) { m.alwaysIncludeClientId = Boolean(d.alwaysIncludeClientId); } if (d.playStartGracePeriodSeconds != null) { if ($util.Long) (m.playStartGracePeriodSeconds = $util.Long.fromValue( d.playStartGracePeriodSeconds )).unsigned = false; else if (typeof d.playStartGracePeriodSeconds === "string") m.playStartGracePeriodSeconds = parseInt( d.playStartGracePeriodSeconds, 10 ); else if (typeof d.playStartGracePeriodSeconds === "number") m.playStartGracePeriodSeconds = d.playStartGracePeriodSeconds; else if (typeof d.playStartGracePeriodSeconds === "object") m.playStartGracePeriodSeconds = new $util.LongBits( d.playStartGracePeriodSeconds.low >>> 0, d.playStartGracePeriodSeconds.high >>> 0 ).toNumber(); } if (d.softEnforcePlaybackDuration != null) { m.softEnforcePlaybackDuration = Boolean(d.softEnforcePlaybackDuration); } if (d.softEnforceRentalDuration != null) { m.softEnforceRentalDuration = Boolean(d.softEnforceRentalDuration); } return m; }; Policy.toObject = function toObject(m, o) { if (!o) o = {}; var d = {}; if (o.defaults) { d.canPlay = false; d.canPersist = false; d.canRenew = false; if ($util.Long) { var n = new $util.Long(0, 0, false); d.rentalDurationSeconds = o.longs === String ? n.toString() : o.longs === Number ? n.toNumber() : n; } else d.rentalDurationSeconds = o.longs === String ? "0" : 0; if ($util.Long) { var n = new $util.Long(0, 0, false); d.playbackDurationSeconds = o.longs === String ? n.toString() : o.longs === Number ? n.toNumber() : n; } else d.playbackDurationSeconds = o.longs === String ? "0" : 0; if ($util.Long) { var n = new $util.Long(0, 0, false); d.licenseDurationSeconds = o.longs === String ? n.toString() : o.longs === Number ? n.toNumber() : n; } else d.licenseDurationSeconds = o.longs === String ? "0" : 0; if ($util.Long) { var n = new $util.Long(0, 0, false); d.renewalRecoveryDurationSeconds = o.longs === String ? n.toString() : o.longs === Number ? n.toNumber() : n; } else d.renewalRecoveryDurationSeconds = o.longs === String ? "0" : 0; d.renewalServerUrl = ""; if ($util.Long) { var n = new $util.Long(0, 0, false); d.renewalDelaySeconds = o.longs === String ? n.toString() : o.longs === Number ? n.toNumber() : n; } else d.renewalDelaySeconds = o.longs === String ? "0" : 0; if ($util.Long) { var n = new $util.Long(0, 0, false); d.renewalRetryIntervalSeconds = o.longs === String ? n.toString() : o.longs === Number ? n.toNumber() : n; } else d.renewalRetryIntervalSeconds = o.longs === String ? "0" : 0; d.renewWithUsage = false; d.alwaysIncludeClientId = false; if ($util.Long) { var n = new $util.Long(0, 0, false); d.playStartGracePeriodSeconds = o.longs === String ? n.toString() :