New
This commit is contained in:
0
pywidevine/decrypt/__init__.py
Normal file
0
pywidevine/decrypt/__init__.py
Normal file
BIN
pywidevine/decrypt/__pycache__/__init__.cpython-36.pyc
Normal file
BIN
pywidevine/decrypt/__pycache__/__init__.cpython-36.pyc
Normal file
Binary file not shown.
BIN
pywidevine/decrypt/__pycache__/__init__.cpython-37.pyc
Normal file
BIN
pywidevine/decrypt/__pycache__/__init__.cpython-37.pyc
Normal file
Binary file not shown.
BIN
pywidevine/decrypt/__pycache__/__init__.cpython-39.pyc
Normal file
BIN
pywidevine/decrypt/__pycache__/__init__.cpython-39.pyc
Normal file
Binary file not shown.
BIN
pywidevine/decrypt/__pycache__/wvdecrypt.cpython-36.pyc
Normal file
BIN
pywidevine/decrypt/__pycache__/wvdecrypt.cpython-36.pyc
Normal file
Binary file not shown.
BIN
pywidevine/decrypt/__pycache__/wvdecrypt.cpython-37.pyc
Normal file
BIN
pywidevine/decrypt/__pycache__/wvdecrypt.cpython-37.pyc
Normal file
Binary file not shown.
BIN
pywidevine/decrypt/__pycache__/wvdecrypt.cpython-39.pyc
Normal file
BIN
pywidevine/decrypt/__pycache__/wvdecrypt.cpython-39.pyc
Normal file
Binary file not shown.
BIN
pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-36.pyc
Normal file
BIN
pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-36.pyc
Normal file
Binary file not shown.
BIN
pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-37.pyc
Normal file
BIN
pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-37.pyc
Normal file
Binary file not shown.
BIN
pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-39.pyc
Normal file
BIN
pywidevine/decrypt/__pycache__/wvdecryptconfig.cpython-39.pyc
Normal file
Binary file not shown.
127
pywidevine/decrypt/wvdecrypt.py
Normal file
127
pywidevine/decrypt/wvdecrypt.py
Normal file
@@ -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
|
||||
|
||||
62
pywidevine/decrypt/wvdecryptconfig.py
Normal file
62
pywidevine/decrypt/wvdecryptconfig.py
Normal file
@@ -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