New
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,127 @@
|
||||
import logging
|
||||
import subprocess
|
||||
import re
|
||||
from tqdm import tqdm
|
||||
import base64
|
||||
import progressbar
|
||||
from time import sleep
|
||||
import binascii
|
||||
|
||||
from pywidevine.cdm import cdm, deviceconfig
|
||||
import pywidevine.downloader.wvdownloaderconfig as wvdl_cfg
|
||||
|
||||
|
||||
class WvDecrypt(object):
|
||||
|
||||
WV_SYSTEM_ID = [237, 239, 139, 169, 121, 214, 74, 206, 163, 200, 39, 220, 213, 29, 33, 237]
|
||||
|
||||
def __init__(self, config):
|
||||
self.config = config
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self.wvdecrypt_process = None
|
||||
self.logger.debug(self.log_message("wvdecrypt object created"))
|
||||
|
||||
self.cdm = cdm.Cdm()
|
||||
|
||||
def check_pssh(pssh_b64):
|
||||
pssh = base64.b64decode(pssh_b64)
|
||||
if not pssh[12:28] == bytes(self.WV_SYSTEM_ID):
|
||||
new_pssh = bytearray([0,0,0])
|
||||
new_pssh.append(32+len(pssh))
|
||||
new_pssh[4:] = bytearray(b'pssh')
|
||||
new_pssh[8:] = [0,0,0,0]
|
||||
new_pssh[13:] = self.WV_SYSTEM_ID
|
||||
new_pssh[29:] = [0,0,0,0]
|
||||
new_pssh[31] = len(pssh)
|
||||
new_pssh[32:] = pssh
|
||||
return base64.b64encode(new_pssh)
|
||||
else:
|
||||
return pssh_b64
|
||||
|
||||
print("binitdata64 " + config.init_data_b64)
|
||||
|
||||
if config.device == 'mpl':
|
||||
self.session = self.cdm.open_session(check_pssh(config.init_data_b64),deviceconfig.DeviceConfig(deviceconfig.device_android_generic_2))
|
||||
else:
|
||||
self.session = self.cdm.open_session(check_pssh(config.init_data_b64),deviceconfig.DeviceConfig(deviceconfig.device_android_generic_2))
|
||||
#print(self.session) device_nexus6_lvl1
|
||||
self.logger.debug(self.log_message("widevine session opened"))
|
||||
if self.config.server_cert_required:
|
||||
self.logger.debug(self.log_message("server cert set"))
|
||||
self.cdm.set_service_certificate(self.session,config.cert_data_b64)
|
||||
|
||||
|
||||
def log_message(self, msg):
|
||||
return "{}_{} : {}".format(self.config.tracktype, self.config.trackno, msg)
|
||||
"""
|
||||
def start_process(self):
|
||||
if self.config.license:
|
||||
for key in self.cdm.get_keys(self.session):
|
||||
if key.type == 'CONTENT':
|
||||
#key.kid.hex()
|
||||
self.logger.logkey(self.log_message('{}:{}'.format(key.kid.hex(),key.key.hex())))
|
||||
else:
|
||||
|
||||
#bar = progressbar.ProgressBar(maxval=progressbar.UnknownLength)#, \
|
||||
|
||||
#widgets=[progressbar.Bar('=', '[', ']'), ' ', progressbar.Percentage()])
|
||||
|
||||
self.logger.debug(self.log_message("starting mp4decrypt process"))
|
||||
self.logger.debug(self.config.build_commandline_list(self.cdm.get_keys(self.session)))
|
||||
print(self.cdm.get_keys(self.session))
|
||||
print(self.config.build_commandline_list(self.cdm.get_keys(self.session)))
|
||||
#exit(1)
|
||||
self.wvdecrypt_process = subprocess.Popen(
|
||||
self.config.build_commandline_list(self.cdm.get_keys(self.session)),
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT
|
||||
)
|
||||
|
||||
|
||||
#i = 0
|
||||
poll = self.wvdecrypt_process.poll()
|
||||
print(poll)
|
||||
#bar.start()
|
||||
while poll is None:
|
||||
#bar.update(i)
|
||||
#sleep(0.1)
|
||||
#i = i +1
|
||||
poll = self.wvdecrypt_process.poll()
|
||||
|
||||
#bar.finish()
|
||||
|
||||
self.wvdecrypt_process.wait()
|
||||
self.logger.debug(self.log_message("mp4decrypt decrypted successfully"))
|
||||
"""
|
||||
|
||||
def start_process(self):
|
||||
#self.key_file = open("key", "w")
|
||||
if self.config.license:
|
||||
for key in self.cdm.get_keys(self.session):
|
||||
if key.type == 'CONTENT':
|
||||
self.logger.logkey(self.log_message('{}:{}'.format(key.kid.hex(),key.key.hex())))
|
||||
#self.key_file.write(key.kid.hex() + ':' + key.key.hex() + '\n')
|
||||
else:
|
||||
self.logger.debug(self.log_message("starting mp4decrypt process"))
|
||||
self.logger.debug(self.config.build_commandline_list(self.cdm.get_keys(self.session)))
|
||||
print(self.cdm.get_keys(self.session))
|
||||
print(self.config.build_commandline_list(self.cdm.get_keys(self.session)))
|
||||
self.wvdecrypt_process = subprocess.Popen(
|
||||
self.config.build_commandline_list(self.cdm.get_keys(self.session)),
|
||||
#stdout=subprocess.PIPE,
|
||||
#stderr=subprocess.STDOUT
|
||||
)
|
||||
self.wvdecrypt_process.wait()
|
||||
self.logger.debug(self.log_message("mp4decrypt decrypted successfully"))
|
||||
#self.key_file.close()
|
||||
|
||||
def get_challenge(self):
|
||||
return self.cdm.get_license_request(self.session)
|
||||
|
||||
def get_sid(self):
|
||||
return (binascii.hexlify(self.session)).decode('utf-8').upper()
|
||||
|
||||
def update_license(self, license_b64):
|
||||
self.cdm.provide_license(self.session, license_b64)
|
||||
return True
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import pywidevine.downloader.wvdownloaderconfig as wvdl_cfg
|
||||
import subprocess
|
||||
|
||||
class WvDecryptConfig(object):
|
||||
def __init__(self, filename, tracktype, trackno, license, init_data_b64, device, cert_data_b64=None):
|
||||
self.filename = filename
|
||||
self.tracktype = tracktype
|
||||
self.trackno = trackno
|
||||
self.init_data_b64 = init_data_b64
|
||||
self.device = device
|
||||
self.license = license
|
||||
if cert_data_b64 is not None:
|
||||
self.server_cert_required = True
|
||||
self.cert_data_b64 = cert_data_b64
|
||||
else:
|
||||
self.server_cert_required = False
|
||||
|
||||
def get_filename(self, unformatted_filename):
|
||||
return unformatted_filename.format(filename=self.filename, track_type=self.tracktype, track_no=self.trackno)
|
||||
|
||||
|
||||
def find_str(self, s, char):
|
||||
index = 0
|
||||
if char in s:
|
||||
c = char[0]
|
||||
for ch in s:
|
||||
if ch == c and s[index:index + len(char)] == char:
|
||||
return index
|
||||
index += 1
|
||||
return -1
|
||||
|
||||
def get_kid(self, filename):
|
||||
mp4dump = subprocess.Popen([wvdl_cfg.MP4DUMP_BINARY_PATH, filename], stdout=subprocess.PIPE)
|
||||
mp4dump = str(mp4dump.stdout.read())
|
||||
A = self.find_str(mp4dump, 'default_KID')
|
||||
KID = mp4dump[A:A + 63].replace('default_KID = ', '').replace('[', '').replace(']', '').replace(' ', '')
|
||||
KID = KID.upper()
|
||||
KID_video = KID[0:8] + '-' + KID[8:12] + '-' + KID[12:16] + '-' + KID[16:20] + '-' + KID[20:32]
|
||||
if KID == '':
|
||||
KID = 'nothing'
|
||||
return KID.lower()
|
||||
|
||||
def build_commandline_list(self, keys):
|
||||
|
||||
KID_file = self.get_kid(self.get_filename(wvdl_cfg.ENCRYPTED_FILENAME))
|
||||
print(KID_file)
|
||||
|
||||
commandline = [wvdl_cfg.MP4DECRYPT_BINARY_PATH]
|
||||
for key in keys:
|
||||
if key.type == 'CONTENT' and key.kid.hex() == KID_file:
|
||||
print("OK")
|
||||
commandline.append('--show-progress')
|
||||
commandline.append('--key')
|
||||
#key.kid.hex()
|
||||
#2 main high 1 hdr dv hevc
|
||||
if 'hdr' in self.get_filename(wvdl_cfg.ENCRYPTED_FILENAME):
|
||||
commandline.append('{}:{}'.format(key.kid.hex(), key.key.hex()))
|
||||
else:
|
||||
commandline.append('{}:{}'.format(key.kid.hex(), key.key.hex()))
|
||||
commandline.append(self.get_filename(wvdl_cfg.ENCRYPTED_FILENAME))
|
||||
commandline.append(self.get_filename(wvdl_cfg.DECRYPTED_FILENAME))
|
||||
return commandline
|
||||
Reference in New Issue
Block a user