Good evening, my friends, I'd like to discuss with you a decryption procedure with site la7.it. As an example, let's consider the following video urlInspecting I can get the data:Code:https://www.la7.it/film-e-fiction/rivedila7/il-processo-di-norimberga-21-06-2024-548773
PSSH
License serverCode:AAAAYXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEEIARIQ01pp2bOiS8CAQtaiuFqJPRoFQ29uYXgiJDk4MWM2ZmY4LWM5NGItNGZhNS04NjYyLTNiYzY2YWQ1ZGM5OA==mpdCode:https://la7.prod.conax.cloud/widevine/license?d=1719420040062When I put license server and PSSH into keysdb.net or some similar site, it returns an error. Should I use a specific header? What do you think? Thank you very, very much in advance for all help and advices. Have a great eveningCode:https://d3iki3eydrtvsa.cloudfront.net/IlProcessoDiNorimberga_20240620211948/DASH/IlProcessoDiNorimberga_20240620211948.mpd![]()
Try StreamFab Downloader and download from Netflix, Amazon, Youtube! Or Try DVDFab and copy Blu-rays! or rip iTunes movies!
+ Reply to Thread
Results 1 to 19 of 19
Thread
-
-
The license request can only be used once, presumably because the JWT (submitted with the "preAuthorization" header) contains a JTI to counter replay attacks.
If you block the license request and use it with your own scripts/tools, it'll return the key:
Code:--key d35a69d9b3a24bc08042d6a2b85a893d:cc97cb1d9d7cc66da2b11b2502d56a3d
-
It worked well for me without blocking the request, I could even get 5 times the key without changing the header.
-
Thank you very much for prompt answer and key. I'd like to understand which header to use, for example in site keysdb.net or https://old.cdrm-project.com/ in order to get the key, as, if I leave the header pane empty, I get an error. Thank you very much for all your help
-
Here is a script that will get the job done for you :
HTML Code:from pywidevine.cdm import Cdm from pywidevine.device import Device from pywidevine.pssh import PSSH import requests import re from bs4 import BeautifulSoup def getkey(preTokenUrl, pssh): pretoken = requests.get(preTokenUrl).json()['preAuthToken'] headers = {'preauthorization': pretoken,} pssh = PSSH(pssh) lic_url = 'https://la7.prod.conax.cloud/widevine/license' device = Device.load(DEVICEPATH) cdm = Cdm.from_device(device) session_id = cdm.open() challenge = cdm.get_license_challenge(session_id, pssh) licence = requests.post(lic_url,headers=headers, data=challenge) licence.raise_for_status() cdm.parse_license(session_id, licence.content) keys = [] for key in cdm.get_keys(session_id): if key.type=='CONTENT': keys.append(f"{key.kid.hex}:{key.key.hex()}") cdm.close(session_id) return keys def getcommand(url): response = requests.get(url) preTokenUrl = re.search(r'preTokenUrl = "(.*?)"', response.text).group(1) videoParams = re.search(r'var videoParams\s*=\s*({.*?});', response.text, re.DOTALL).group(1) videoParams_clean = re.sub(r'([a-zA-Z_]+)\s*:', r'"\1":', videoParams).replace('"https"', 'https') mpd_url = re.search(r'"dash"\s*:\s*"([^"]+)"', videoParams_clean).group(1) title = re.search(r'"title"\s*:\s*"([^"]+)"', videoParams_clean).group(1) pssh = BeautifulSoup(requests.get(mpd_url).text, 'lxml-xml').findAll('cenc:pssh')[1].text keys = getkey(preTokenUrl, pssh) print(f"""N_m3u8DL-RE "{mpd_url}" --save-name "{title}" --select-video best --select-audio all --select-subtitle all -mt -M format=mkv --log-level OFF --key """ + ' --key '.join(keys)) # vidurl = 'https://www.la7.it/film-e-fiction/rivedila7/il-processo-di-norimberga-21-06-2024-548773' DEVICEPATH = "device.wvd" vidurl = input('Enter the URL of the video: ') getcommand(vidurl)
For exemple for : https://www.la7.it/film-e-fiction/rivedila7/il-processo-di-norimberga-21-06-2024-548773 the script return :
Code:N_m3u8DL-RE "https://d3iki3eydrtvsa.cloudfront.net/IlProcessoDiNorimberga_20240620211948/DASH/IlProcessoDiNorimberga_20240620211948.mpd" --save-name "Il processo di Norimberga" --select-video best --select-audio all --select-subtitle all -mt -M format=mkv --log-level OFF --key d35a69d9b3a24bc08042d6a2b85a893d:cc97cb1d9d7cc66da2b11b2502d56a3d
Last edited by aqzs; 26th Jun 2024 at 14:12.
-
@aqzs, then I might have been really unlucky that the JWT expired below my fingers. The JWT has a lifetime of a couple minutes.
@misek1963: I guess you'll need at least the preAuthorization header. But haven't tested it. -
-
Yeah, but before writing a script you'll have to analyze the network requests first and manually try what has to be done...
For expire times and generally payload of JWTs simply paste them at https://jwt.io/ -
I usually copy raw curl from network tab, if I see an JWT token I search for it in network tab too and copy the request a curl too. I try removing every part from header that can be removed and automate everything. That's how I mad this script : https://forum.videohelp.com/threads/415062-Help-with-la7-it#post2740871 and many others I shared here ^^
-
JWT token are json base64 encoded. You can read them with that script :
HTML Code:import json import base64 from pprint import pprint def jd64(input): try: return json.loads(base64.b64decode(input)) except base64.binascii.Error : if '====' in input: return 'Invalid base64-encoded string' else: return jd64(input+'=') tokenpart = 'eyJhbGciOiJFUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ' pprint(jd64(tokenpart))
-
Yes, I know. I have my own script to decode them. Which I usually do if I see one.
-
Thank you very, very much, for the script tailored for my need. I've grabbed the CDM and now I've got the two files
Code:device_client_id_blob.bin
Code:device_private_key.pem
Code:T:\Pythonult\
-
With those 2 files you need to make a CDM using that command :
Code:pywidevine create-device -k device_private_key -c device_client_id_blob -t ANDROID -l3 -o WVD
Code:pywidevine create-device -k device_private_key.pem -c device_client_id_blob.bin -t ANDROID -l3 -o WVD
-
Thank you so much for the code. I've followed your advices and now I've got the following file
Code:unknown_android_sdk_built_for_x86_16.0.0_9d1ea0a0_8162_l3.wvd
Code:t:\Puthonult\WVD
Code:t:\Puthonult\WVD\unknown_android_sdk_built_for_x86_16.0.0_9d1ea0a0_8162_l3.wvd
-
in the script write :
Code:DEVICEPATH = 't:/Puthonult/WVD/unknown_android_sdk_built_for_x86_16.0.0_9d1ea0a0_8162_l3.wvd'
-
Thank you very much, really, for all your so kind help and efforts in explaining in detail all steps. After modifying the script I've been able to launch it. Anyway after inserting the video url (video plays in browser) I get the following error messages
Code:la7.py Enter the URL of the video: https://www.la7.it/film-e-fiction/rivedila7/il-processo-di-norimberga-21-06-2024-548773 Traceback (most recent call last): File "T:\Pythonult\la7.py", line 49, in <module> getcommand(vidurl) File "T:\Pythonult\la7.py", line 41, in getcommand pssh = BeautifulSoup(requests.get(mpd_url).text, 'lxml-xml').findAll('cenc:pssh')[1].text ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "T:\Python39\Lib\site-packages\bs4\__init__.py", line 250, in __init__ raise FeatureNotFound( bs4.FeatureNotFound: Couldn't find a tree builder with the features you requested: lxml-xml. Do you need to install a parser library?
-
-
After some trials and errors I get this message
Code:Requirement already satisfied: lxml in t:\pythonult\lib\site-packages (5.2.1)
Last edited by misiek1963; 28th Jun 2024 at 14:07.