forked from medvm/widevine_keys
-
Notifications
You must be signed in to change notification settings - Fork 0
/
l3.py
133 lines (124 loc) · 4.72 KB
/
l3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# -*- coding: utf-8 -*-
# Module: widevine_keys
# Created on: 10.12.2021
# Authors: medvm
# Version: 2.1.0
import base64, requests, sys, xmltodict
import headers
# import cookies
import json
from cdm import cdm, deviceconfig
from base64 import b64encode
from getPSSH import get_pssh
from wvdecryptcustom import WvDecrypt
from cdm.formats import wv_proto2_pb2 as wv_proto2
from urllib.parse import urlparse
import logging
# logging.basicConfig(level=logging.DEBUG)
MDP_URL = input('\nInput MPD URL: ')
lic_url = input('License URL: ')
# hardcoded for kinopoisk.ru
# lic_url = 'https://widevine-proxy.ott.yandex.ru/proxy'
responses = []
license_b64 = ''
pssh = get_pssh(MDP_URL)
params = None
params = urlparse(lic_url).query
# pssh = 'AAAAXHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADwIARIQ7iYSc3cNGm7XKPe3hSn3MhoIdXNwLWNlbmMiGDdpWVNjM2NOR203WEtQZTNoU24zTWc9PSoAMgA='
# params from mdp_url:
# ottsession=5945048d6f844d1699054cc5d44548f1&
# puid=339572866&
# video_content_id=4315082489d87677b21f7c83593fcb73&
print(f'{chr(10)}PSSH obtained.\n{pssh}')
def WV_Function(pssh, lic_url, cert_b64=None):
"""main func, emulates license request and then decrypt obtained license
fileds that changes every new request is signature, expirationTimestamp, watchSessionId, puid, and rawLicenseRequestBase64 """
wvdecrypt = WvDecrypt(init_data_b64=pssh, cert_data_b64=cert_b64, device=deviceconfig.device_android_generic)
raw_request = wvdecrypt.get_challenge()
request = b64encode(raw_request)
signature = cdm.hash_object
# basic, mostly sites works
responses.append(requests.post(url=lic_url, headers=headers.headers, data=raw_request, params=params))
# some another sites support
responses.append(requests.post(url=lic_url, headers=headers.headers, params=params,
json={
"rawLicenseRequestBase64": str(request, "utf-8" ),
}))
# kakaotv support
responses.append(requests.post(url=lic_url, headers=headers.headers, params=params,
data=f'token={headers.token}&provider={headers.provider}&payload={str(request, "utf-8" )}'
))
# xfinity.com support
headers.headers['licenseRequest'] = str(request, "utf-8" )
responses.append(requests.post(url=lic_url, headers=headers.headers, params=params,
))
del headers.headers['licenseRequest']
# rte.ie support
responses.append(requests.post(url=lic_url, headers=headers.headers, params=params,
json={
"getWidevineLicense":
{
'releasePid': headers.releasePid,
'widevineChallenge': str(request, "utf-8" )
},
}))
# kinopoisk support
responses.append(requests.post(url=lic_url, headers=headers.headers, params=params,
json={
"rawLicenseRequestBase64": str(request, "utf-8" ),
"puid": '339572866',
"watchSessionId": 'ed0e355063ac48b783130a390dc27ba6',
"contentId": '4315082489d87677b21f7c83593fcb73',
"contentTypeId": '21',
"serviceName": 'ott-kp',
"productId": '2',
"monetizationModel": 'SVOD',
"expirationTimestamp": '1639009453',
"verificationRequired": 'false',
"signature": str(signature),
"version": 'V4'
}))
for idx, response in enumerate(responses):
try:
str(response.content, "utf-8")
except UnicodeDecodeError:
widevine_license = response
print(f'{chr(10)}license response status: {widevine_license}{chr(10)}')
break
else:
if len(str(response.content, "utf-8")) > 500:
widevine_license = response
print(f'{chr(10)}license response status: {widevine_license}{chr(10)}')
break
if idx == len(responses) - 1:
print(f'{chr(10)}license response status: {response}')
print(f'server reports: {str(response.content, "utf-8")}')
print(f'server did not issue license, make sure you have correctly pasted all the required headers in the headers.py. Also check json/raw params of POST request.{chr(10)}')
exit()
lic_field_names = ['license', 'payload', 'getWidevineLicenseResponse']
lic_field_names2 = ['license']
open('license_content.bin', 'wb').write(widevine_license.content)
try:
if str(widevine_license.content, 'utf-8').find(':'):
for key in lic_field_names:
try:
license_b64 = json.loads(widevine_license.content.decode())[key]
except:
pass
else:
for key2 in lic_field_names2:
try:
license_b64 = json.loads(widevine_license.content.decode())[key][key2]
except:
pass
else:
license_b64 = widevine_license.content
except:
license_b64 = b64encode(widevine_license.content)
wvdecrypt.update_license(license_b64)
Correct, keyswvdecrypt = wvdecrypt.start_process()
if Correct:
return Correct, keyswvdecrypt
correct, keys = WV_Function(pssh, lic_url)
for key in keys:
print('KID:KEY -> ' + key)