mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2025-10-23 15:11:08 +00:00
feat(cdm): Enhance DecryptLabsRemoteCDM to support cached keys and improve license handling
This commit is contained in:
@@ -26,7 +26,9 @@ class DecryptLabsRemoteCDM(RemoteCdm):
|
||||
self.api_session_ids = {}
|
||||
self.license_request = None
|
||||
self.service_name = service_name
|
||||
self.device_name = device_name
|
||||
self.keys = {}
|
||||
self.scheme = "L1" if device_name == "L1" else "widevine"
|
||||
try:
|
||||
super().__init__(device_type, system_id, security_level, host, secret, device_name)
|
||||
except Exception:
|
||||
@@ -66,16 +68,49 @@ class DecryptLabsRemoteCDM(RemoteCdm):
|
||||
) -> bytes:
|
||||
self.pssh = pssh
|
||||
|
||||
res = self.session(
|
||||
self.host + "/get-request",
|
||||
{
|
||||
request_data = {
|
||||
"init_data": self.pssh.dumps(),
|
||||
"service_certificate": self.req_session.signed_device_certificate,
|
||||
"scheme": "widevine",
|
||||
"scheme": self.scheme,
|
||||
"service": self.service_name,
|
||||
},
|
||||
}
|
||||
# Add required parameter for L1 scheme
|
||||
if self.scheme == "L1":
|
||||
request_data["get_cached_keys_if_exists"] = True
|
||||
res = self.session(
|
||||
self.host + "/get-request",
|
||||
request_data,
|
||||
)
|
||||
|
||||
# Check if we got cached keys instead of a challenge
|
||||
if res.get("message_type") == "cached-keys":
|
||||
# Store cached keys directly
|
||||
if session_id not in self.keys:
|
||||
self.keys[session_id] = []
|
||||
session_keys = self.keys[session_id]
|
||||
|
||||
for cached_key in res.get("cached_keys", []):
|
||||
# Handle KID format - could be hex string or UUID string
|
||||
kid_str = cached_key["kid"]
|
||||
try:
|
||||
# Try as UUID string first
|
||||
kid_uuid = UUID(kid_str)
|
||||
except ValueError:
|
||||
try:
|
||||
# Try as hex string (like the existing code)
|
||||
kid_uuid = UUID(bytes=bytes.fromhex(kid_str))
|
||||
except ValueError:
|
||||
# Fallback: use Key.kid_to_uuid
|
||||
kid_uuid = Key.kid_to_uuid(kid_str)
|
||||
|
||||
session_keys.append(Key(kid=kid_uuid, type_="CONTENT", key=bytes.fromhex(cached_key["key"])))
|
||||
|
||||
# Return empty challenge since we already have the keys
|
||||
self.license_request = ""
|
||||
self.api_session_ids[session_id] = None
|
||||
return b""
|
||||
|
||||
# Normal challenge response
|
||||
self.license_request = res["challenge"]
|
||||
self.api_session_ids[session_id] = res["session_id"]
|
||||
|
||||
@@ -87,6 +122,10 @@ class DecryptLabsRemoteCDM(RemoteCdm):
|
||||
self.keys[session_id] = []
|
||||
session_keys = self.keys[session_id]
|
||||
|
||||
# If we already have cached keys and no session_id_api, skip processing
|
||||
if session_id_api is None and session_keys:
|
||||
return
|
||||
|
||||
if isinstance(license_message, dict) and "keys" in license_message:
|
||||
session_keys.extend(
|
||||
[
|
||||
@@ -96,14 +135,21 @@ class DecryptLabsRemoteCDM(RemoteCdm):
|
||||
)
|
||||
|
||||
else:
|
||||
# Ensure license_message is base64 encoded
|
||||
if isinstance(license_message, bytes):
|
||||
license_response_b64 = base64.b64encode(license_message).decode()
|
||||
elif isinstance(license_message, str):
|
||||
license_response_b64 = license_message
|
||||
else:
|
||||
license_response_b64 = str(license_message)
|
||||
res = self.session(
|
||||
self.host + "/decrypt-response",
|
||||
{
|
||||
"session_id": session_id_api,
|
||||
"init_data": self.pssh.dumps(),
|
||||
"license_request": self.license_request,
|
||||
"license_response": license_message,
|
||||
"scheme": "widevine",
|
||||
"license_response": license_response_b64,
|
||||
"scheme": self.scheme,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user