The DouyuTV plugin function works fine yesterday. (2019/2/25)
At least
streams = streamlink.streams("https://www.douyu.com/3284257")
works through Python
But today it seems Douyu change some of its setting.
streamlink.exceptions.PluginError: Unable to open URL: https://capi.douyucdn.cn/api/v1/room/3284257?aid=wp&cdn=ws&client_sys=wp&time=1551152907&auth=0d8a7d105628da346bd088e19cdcdbca (401 Client Error: Unauthorized for url: https://capi.douyucdn.cn/api/v1/room/3284257?aid=wp&cdn=ws&client_sys=wp&time=1551152907&auth=0d8a7d105628da346bd088e19cdcdbca)
same issue, any 1 has any ideas?
same issue, any 1 has any ideas?
same issue
Posting "same" doesn't contribute anything to this issue. Please don't do that.
If you want to contribute to this issue, please post a proper debug log, since this hasn't been done here yet, even though it is required for a full plugin issue report.
Plugin error: Unable to open URL: https://capi.douyucdn.cn/api/v1/room/718133?aid=wp&cdn=ws&client_sys=wp&time=1551160101&auth=ebb7921a90c2b6f4ed679bbf41095800 (401 Client Error: Unauthorized for url: https://capi.douyucdn.cn/api/v1/room/718133?aid=wp&cdn=ws&client_sys=wp&time=1551160101&auth=ebb7921a90c2b6f4ed679bbf41095800)
if you open this url ,it normally return a file,but it return a "401 Authorization Required" error since this morning.

@bastimeyer
from streamlink import Streamlink, StreamError, PluginError, NoPluginError
import streamlink
url = "https://www.douyu.com/8733"
try:
streams = streamlink.streams(url)
except NoPluginError:
exit("Streamlink is unable to handle the URL '{0}'".format(url))
except PluginError as err:
exit("Plugin error: {0}".format(err))
Plugin error: Unable to open URL: https://capi.douyucdn.cn/api/v1/room/8733?aid=wp&cdn=ws2&client_sys=wp&time=1551188172&auth=3b0b1d5491a8cbb31e437aaac1646091 (401 Client Error: Unauthorized for url: https://capi.douyucdn.cn/api/v1/room/8733?aid=wp&cdn=ws2&client_sys=wp&time=1551188172&auth=3b0b1d5491a8cbb31e437aaac1646091)
Please run streamlink -l debug https://www.douyu.com/8733 best to generate a useful debug log.
C:\Users\y>streamlink -l debug https://www.douyu.com/8733 best
[cli][debug] OS: Windows 10
[cli][debug] Python: 3.6.0
[cli][debug] Streamlink: 1.0.0
[cli][debug] Requests(2.21.0), Socks(1.6.7), Websocket(0.54.0)
[cli][info] Found matching plugin douyutv for URL https://www.douyu.com/8733
error: Unable to open URL: https://capi.douyucdn.cn/api/v1/room/8733?aid=wp&cdn=ws&client_sys=wp&time=1551188621&auth=0e60a401efe9a968d56c464f9154ace6 (401 Client Error: Unauthorized for url: https://capi.douyucdn.cn/api/v1/room/8733?aid=wp&cdn=ws&client_sys=wp&time=1551188621&auth=0e60a401efe9a968d56c464f9154ace6)
@beardypig
streamlink -l debug https://www.douyu.com/8733 best
[Streamlink for Windows v0.14.0 - Git 4f5bb1e]
[cli][debug] OS: Windows 10
[cli][debug] Python: 3.6.3
[cli][debug] Streamlink: 0.14.0@4f5bb1e
[cli][debug] Requests(2.18.4), Socks(1.6.7), Websocket(0.44.0)
[cli][info] Found matching plugin douyutv for URL https://www.douyu.com/8733
error: Unable to open URL: https://capi.douyucdn.cn/api/v1/room/8733?aid=wp&cdn=ws&client_sys=wp&time=1551188648&auth=9cae1a06dac7625e605f9c5554efdb4e (401 Client Error: Unauthorized for url: https://capi.douyucdn.cn/api/v1/room/8733?aid=wp&cdn=ws&client_sys=wp&time=1551188648&auth=9cae1a06dac7625e605f9c5554efdb4e)
[End of Streamlink for Windows with ExitCode 1]
[root@izwz937q6lqzqqxijq89z1z ~]# /usr/local/python3/bin/streamlink -l debug https://www.douyu.com/8733 best
[cli][info] streamlink is running as root! Be careful!
[cli][debug] OS: Linux-3.10.0-514.26.2.el7.x86_64-x86_64-with-centos-7.6.1810-Core
[cli][debug] Python: 3.6.5
[cli][debug] Streamlink: 1.0.0
[cli][debug] Requests(2.21.0), Socks(1.6.7), Websocket(0.54.0)
[cli][info] Found matching plugin douyutv for URL https://www.douyu.com/8733
error: Unable to open URL: https://capi.douyucdn.cn/api/v1/room/8733?aid=wp&cdn=ws&client_sys=wp&time=1551188711&auth=2773f35a559684c6d99e8e68cbcce918 (401 Client Error: Unauthorized for url: https://capi.douyucdn.cn/api/v1/room/8733?aid=wp&cdn=ws&client_sys=wp&time=1551188711&auth=2773f35a559684c6d99e8e68cbcce918)
[cli][debug] OS: Windows 10
[cli][debug] Python: 3.6.2
[cli][debug] Streamlink: 1.0.0
[cli][debug] Requests(2.21.0), Socks(1.6.7), Websocket(0.55.0)
[cli][info] Found matching plugin douyutv for URL https://www.douyu.com/8733
error: Unable to open URL: https://capi.douyucdn.cn/api/v1/room/8733?aid=wp&cdn=ws&client_sys=wp&time=1551192413&auth=70163b7309d0a5465db7a72debff70ec (401 Client Error: Unauthorized for url: https://capi.douyucdn.cn/api/v1/room/8733?aid=wp&cdn=ws&client_sys=wp&time=1551192413&auth=70163b7309d0a5465db7a72debff70ec)

the new official app client of douyu, no Ads, no donation ....
you guys could have this as temporary one.
斗鱼可能的确要凉了,弄这种完全没打赏和广告的客户端出来,除了卖个人隐私跟踪,上市前冲量,有什么良性意义?
因此可估计,要凉的斗鱼还会疯狂封杀折腾取流工具。这次不过是刚开始。
另,貌似还有几个api没被封。
please refer to https://github.com/xjbeta/iina-plus/issues/14
js: get_sign
function get_sign(rid, dy_did, tt) { var cb = rid + dy_did + tt + "220120190227"; var rb = CryptoJS.MD5(cb).toString(); var re = []; for (var i = 0; i < rb.length / 8; i++) re[i] = (parseInt(rb.substr(i * 8, 2), 16) & 0xff) | ((parseInt(rb.substr(i * 8 + 2, 2), 16) << 8) & 0xff00) | ((parseInt(rb.substr(i * 8 + 4, 2), 16) << 24) >>> 8) | (parseInt(rb.substr(i * 8 + 6, 2), 16) << 24); var k2 = [0x426d8845, 0x59edcc2d, 0x365400, 0x31b96b4d]; for (var I = 0; I < 2; I++) { var v0 = re[I * 2], v1 = re[I * 2 + 1], sum = 0, i = 0; var delta = 0x9e3779b9; for (i = 0; i < 32; i++) { sum += delta; v0 += ((v1 << 4) + k2[0]) ^ (v1 + sum) ^ ((v1 >>> 5) + k2[1]); v1 += ((v0 << 4) + k2[2]) ^ (v0 + sum) ^ ((v0 >>> 5) + k2[3]); } re[I * 2] = v0; re[I * 2 + 1] = v1; } re[0] ^= k2[0]; re[0] ^= k2[2]; re[0] ^= k2[0]; re[0] -= k2[2]; re[1] = (re[1] >>> (k2[1] % 16)) | (re[1] << (32 - (k2[1] % 16))); re[1] ^= k2[3]; re[1] = (re[1] >>> (k2[3] % 16)) | (re[1] << (32 - (k2[3] % 16))); re[2] = (re[2] >>> (k2[0] % 16)) | (re[2] << (32 - (k2[0] % 16))); re[2] += k2[2]; re[2] -= k2[2]; re[3] -= k2[1]; re[3] ^= k2[3]; re[3] -= k2[3]; re[0] -= k2[0]; re[0] += k2[2]; re[0] = (re[0] >>> (k2[2] % 16)) | (re[0] << (32 - (k2[2] % 16))); re[1] = (re[1] << (k2[1] % 16)) | (re[1] >>> (32 - (k2[1] % 16))); re[1] ^= k2[3]; re[1] ^= k2[3]; re[2] += k2[0]; re[2] = (re[2] >>> (k2[2] % 16)) | (re[2] << (32 - (k2[2] % 16))); re[2] = (re[2] >>> (k2[0] % 16)) | (re[2] << (32 - (k2[0] % 16))); re[2] += k2[2]; re[2] = (re[2] << (k2[2] % 16)) | (re[2] >>> (32 - (k2[2] % 16))); re[3] += k2[1]; re[3] = (re[3] << (k2[3] % 16)) | (re[3] >>> (32 - (k2[3] % 16))); re[3] += k2[3]; re[3] = (re[3] << (k2[3] % 16)) | (re[3] >>> (32 - (k2[3] % 16))); { var hc = '0123456789abcdef'.split(''); for (var i = 0; i < re.length; i++) { var j = 0, s = ''; for (; j < 4; j++) s += hc[(re[i] >> (j * 8 + 4)) & 15] + hc[(re[i] >> (j * 8)) & 15]; re[i] = s; } re = re.join(''); } return re; }pseudocode: get_douyu_rtmp_url
def get_douyu_rtmp_url(room_id): cookie = get_cookie() # example: # cookie: dy_did=10ab4930def0490493e0a0b0c29573f1; acf_did=10ab4930def0490493e0a0b0c29573f1; ... # dy_did = 10ab4930def0490493e0a0b0c29573f1 rid = str(room_id) tt = str(time.time()) values = { "v": 220120190227, "did": dy_did, "tt": tt, "sign": get_sign(rid, dy_did, tt), "cdn": "", "rate": 0, "ver": "Douyu_219022605", "iar": 1, "ive": 0, } headers = { 'Accept':'application/json, text/plain, */*', 'Accept-Encoding':'gzip, deflate, br', 'Accept-Language':'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7', 'Content-Type': 'application/x-www-form-urlencoded', 'Cookie': cookie, 'DNT':'1', 'Origin':'https://www.douyu.com', 'Referer':'https://www.douyu.com/' + rid, 'User-Agent':'Mozilla/5.0', 'X-Requested-With':'XMLHttpRequest'} data = urllib.urlencode(values) url = "https://www.douyu.com/lapi/live/getH5Play/" + rid request = urllib2.Request(url, data, headers)# post response = urllib2.urlopen(request) json_data = response.read() print json_datajson_data: example
{ "error": 0, "msg": "ok", "data": { "room_id": 2268066, "is_mixed": false, "mixed_live": "", "mixed_url": "", "rtmp_cdn": "ws-h5", "rtmp_url": "https://hdls3a.douyucdn.cn/live", "rtmp_live": "yyyyyyyyyyyyyyyyyyyyyyyyy", "client_ip": "xxx.xxx.xxx.xxx", "inNA": 0, "rateSwitch": 0, "rate": 0, "cdnsWithName": [ { "name": "主线路", "cdn": "ws-h5" }, { "name": "备用线路5", "cdn": "tct-h5" } ], "multirates": [ { "name": "超清", "rate": 0, "highBit": 0 } ], "isPassPlayer": 0, "eticket": null, "online": 0, "mixedCDN": "", "p2p": 2, "streamStatus": 1 } }
通过 https://www.douyu.com/lapi/live/getH5Play 获取的 rtmp_url/rtmp_live 好像是分段的,只能播放几秒就会断
斗鱼将h5player的流改成了一段段小的流量包了
The live stream URL is formatted with rtmp_url/rtmp_live, it should be parsed out by POST to "https://www.douyu.com/lapi/live/getH5Play" with necessary parameters.
Unfortunately, DouYu TV seems split the steam data into lots of small pieces, each piece of stream data will be broken after a few seconds.
please refer to xjbeta/iina-plus#14
js: get_sign
function get_sign(rid, dy_did, tt)
{
var cb = rid + dy_did + tt + "220120190227";
var rb = CryptoJS.MD5(cb).toString();
var re = [];
for (var i = 0; i < rb.length / 8; i++)
re[i] = (parseInt(rb.substr(i * 8, 2), 16) & 0xff) | ((parseInt(rb.substr(i * 8 + 2, 2), 16) << 8) & 0xff00) | ((parseInt(rb.substr(i * 8 + 4, 2), 16) << 24) >>> 8) | (parseInt(rb.substr(i * 8 + 6, 2), 16) << 24);var k2 = [0x426d8845, 0x59edcc2d, 0x365400, 0x31b96b4d]; for (var I = 0; I < 2; I++) { var v0 = re[I * 2], v1 = re[I * 2 + 1], sum = 0, i = 0; var delta = 0x9e3779b9; for (i = 0; i < 32; i++) { sum += delta; v0 += ((v1 << 4) + k2[0]) ^ (v1 + sum) ^ ((v1 >>> 5) + k2[1]); v1 += ((v0 << 4) + k2[2]) ^ (v0 + sum) ^ ((v0 >>> 5) + k2[3]); } re[I * 2] = v0; re[I * 2 + 1] = v1; } re[0] ^= k2[0]; re[0] ^= k2[2]; re[0] ^= k2[0]; re[0] -= k2[2]; re[1] = (re[1] >>> (k2[1] % 16)) | (re[1] << (32 - (k2[1] % 16))); re[1] ^= k2[3]; re[1] = (re[1] >>> (k2[3] % 16)) | (re[1] << (32 - (k2[3] % 16))); re[2] = (re[2] >>> (k2[0] % 16)) | (re[2] << (32 - (k2[0] % 16))); re[2] += k2[2]; re[2] -= k2[2]; re[3] -= k2[1]; re[3] ^= k2[3]; re[3] -= k2[3]; re[0] -= k2[0]; re[0] += k2[2]; re[0] = (re[0] >>> (k2[2] % 16)) | (re[0] << (32 - (k2[2] % 16))); re[1] = (re[1] << (k2[1] % 16)) | (re[1] >>> (32 - (k2[1] % 16))); re[1] ^= k2[3]; re[1] ^= k2[3]; re[2] += k2[0]; re[2] = (re[2] >>> (k2[2] % 16)) | (re[2] << (32 - (k2[2] % 16))); re[2] = (re[2] >>> (k2[0] % 16)) | (re[2] << (32 - (k2[0] % 16))); re[2] += k2[2]; re[2] = (re[2] << (k2[2] % 16)) | (re[2] >>> (32 - (k2[2] % 16))); re[3] += k2[1]; re[3] = (re[3] << (k2[3] % 16)) | (re[3] >>> (32 - (k2[3] % 16))); re[3] += k2[3]; re[3] = (re[3] << (k2[3] % 16)) | (re[3] >>> (32 - (k2[3] % 16))); { var hc = '0123456789abcdef'.split(''); for (var i = 0; i < re.length; i++) { var j = 0, s = ''; for (; j < 4; j++) s += hc[(re[i] >> (j * 8 + 4)) & 15] + hc[(re[i] >> (j * 8)) & 15]; re[i] = s; } re = re.join(''); } return re;}
pseudocode: get_douyu_rtmp_url
def get_douyu_rtmp_url(room_id):
cookie = get_cookie()
# example:
# cookie: dy_did=10ab4930def0490493e0a0b0c29573f1; acf_did=10ab4930def0490493e0a0b0c29573f1; ...
# dy_did = 10ab4930def0490493e0a0b0c29573f1rid = str(room_id) tt = str(time.time()) values = { "v": 220120190227, "did": dy_did, "tt": tt, "sign": get_sign(rid, dy_did, tt), "cdn": "", "rate": 0, "ver": "Douyu_219022605", "iar": 1, "ive": 0, } headers = { 'Accept':'application/json, text/plain, */*', 'Accept-Encoding':'gzip, deflate, br', 'Accept-Language':'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7', 'Content-Type': 'application/x-www-form-urlencoded', 'Cookie': cookie, 'DNT':'1', 'Origin':'https://www.douyu.com', 'Referer':'https://www.douyu.com/' + rid, 'User-Agent':'Mozilla/5.0', 'X-Requested-With':'XMLHttpRequest'} data = urllib.urlencode(values) url = "https://www.douyu.com/lapi/live/getH5Play/" + rid request = urllib2.Request(url, data, headers)# post response = urllib2.urlopen(request) json_data = response.read() print json_datajson_data: example
{
"error": 0,
"msg": "ok",
"data": {
"room_id": 2268066,
"is_mixed": false,
"mixed_live": "",
"mixed_url": "",
"rtmp_cdn": "ws-h5",
"rtmp_url": "https://hdls3a.douyucdn.cn/live",
"rtmp_live": "yyyyyyyyyyyyyyyyyyyyyyyyy",
"client_ip": "xxx.xxx.xxx.xxx",
"inNA": 0,
"rateSwitch": 0,
"rate": 0,
"cdnsWithName": [
{
"name": "主线路",
"cdn": "ws-h5"
},
{
"name": "备用线路5",
"cdn": "tct-h5"
}
],
"multirates": [
{
"name": "超清",
"rate": 0,
"highBit": 0
}
],
"isPassPlayer": 0,
"eticket": null,
"online": 0,
"mixedCDN": "",
"p2p": 2,
"streamStatus": 1
}
}通过 https://www.douyu.com/lapi/live/getH5Play 获取的 rtmp_url/rtmp_live 好像是分段的,只能播放几秒就会断
斗鱼将h5player的流改成了一段段小的流量包了
The live stream URL is formatted with rtmp_url/rtmp_live, it should be parsed out by POST to "https://www.douyu.com/lapi/live/getH5Play" with necessary parameters.
Unfortunately, DouYu TV seems split the steam data into lots of small pieces, each piece of stream data will be broken after a few seconds.
Hi, I am not sure if you have just provided another approach for API of DouyuTV, as I am not familiar with this plugin.
However, based on my observe, in the past, Streamlink would detect many HLS urls of DouyuTV for a given room url. A few of them store a single 4/8 seconds playable video stream data, the others are unpacked secondary video url, which constantly receiving stream data (4s/8s) and those split video streams' stored url are also trackable. So that is why I feel you may have just provided a different approach...
https://github.com/soimort/you-get/pull/2686
这个我在you-get改写的,可以工作,但需要安装新的依赖库requests_html和
Chromium,大家看看能不能修改后更好地工作
thanks for the encrypt algorithm in js, I've made a python version and work on fixing douyutv plugin.
def douyu_sign(rid, did, tt):
cb = rid + did + tt + '220120190227'
m1 = hashlib.md5()
m1.update(cb.encode('ascii'))
rb = m1.hexdigest()
re = list()
for i in range(len(rb) // 8):
c = (int(rb[i*8: i*8+2], 16) & 0xff) | ((int(rb[i*8+2: i*8+4], 16) << 8) & 0xff00) | ((int(rb[i*8+4: i*8+6], 16) << 24) >> 8) | (int(rb[i*8+6: i*8+8], 16) << 24)
re.append(c)
k2 = [0x426d8845, 0x59edcc2d, 0x365400, 0x31b96b4d]
for i in range(2):
v0 = re[i*2]
v1 = re[i*2+1]
csum = 0
delta = 0x9e3779b9
for j in range(32):
csum += delta
v0 += ((v1 << 4) + k2[0]) ^ (v1 + csum) ^ ((v1 >> 5) + k2[1])
v1 += ((v0 << 4) + k2[2]) ^ (v0 + csum) ^ ((v0 >> 5) + k2[3])
re[i*2] = v0
re[i*2+1] = v1
re[0] ^= k2[0]
re[0] ^= k2[2]
re[0] ^= k2[0]
re[0] -= k2[2]
re[1] = (re[1] >> (k2[1] % 16)) | (re[1] << (32 - (k2[1] % 16)))
re[1] ^= k2[3]
re[1] = (re[1] >> (k2[3] % 16)) | (re[1] << (32 - (k2[3] % 16)))
re[2] = (re[2] >> (k2[0] % 16)) | (re[2] << (32 - (k2[0] % 16)))
re[3] -= k2[1]
re[3] ^= k2[3]
re[3] -= k2[3]
re[0] -= k2[0]
re[0] += k2[2]
re[0] = (re[0] >> (k2[2] % 16)) | (re[0] << (32 - (k2[2] % 16)))
re[1] = (re[1] << (k2[1] % 16)) | (re[1] >> (32 - (k2[1] % 16)))
re[2] += k2[0]
re[2] = (re[2] >> (k2[2] % 16)) | (re[2] << (32 - (k2[2] % 16)))
re[2] = (re[2] >> (k2[0] % 16)) | (re[2] << (32 - (k2[0] % 16)))
re[2] += k2[2]
re[2] = (re[2] << (k2[2] % 16)) | (re[2] >> (32 - (k2[2] % 16)))
re[3] += k2[1]
re[3] = (re[3] << (k2[3] % 16)) | (re[3] >> (32 - (k2[3] % 16)))
re[3] += k2[3]
re[3] = (re[3] << (k2[3] % 16)) | (re[3] >> (32 - (k2[3] % 16)))
hc = list('0123456789abcdef')
for i in range(len(re)):
s = ''
for j in range(4):
s += hc[(re[i] >> (j * 8 + 4)) & 15] + hc[(re[i] >> (j * 8)) & 15]
re[i] = s
re = ''.join(re)
return re
update1: there are still some problem in the algorithm, I am trying to find out the errors.
there are problems with the unfixed int length in python, I think a third-party library such as numpy is needed.
import hashlib
import sys
import numpy as np
def douyu_sign(rid, did, tt):
print("roomid: {}, did: {}, tt: {}".format(rid, did, tt))
cb = rid + did + tt + '220120190227'
m1 = hashlib.md5()
m1.update(cb.encode('ascii'))
rb = m1.hexdigest()
re = list()
for i in range(len(rb) // 8):
rb_8i_0 = np.int32(int(rb[i*8: i*8+2], 16))
rb_8i_2 = np.int32(int(rb[i*8+2: i*8+4], 16))
rb_8i_4 = np.int32(int(rb[i*8+4: i*8+6], 16))
rb_8i_6 = np.int32(int(rb[i*8+6: i*8+8], 16))
p1 = rb_8i_0 & np.int32(0xff)
p2 = rb_8i_2 << 8
p2 = p2 & np.int32(0xff00)
p3 = rb_8i_4 << 24
up3 = np.uint32(p3)
p3 = up3 >> 8
p4 = rb_8i_6 << 24
c = p1 | p2 | p3 | p4
re.append(c)
k2 = np.array([0x426d8845, 0x59edcc2d, 0x365400, 0x31b96b4d], dtype=np.int64)
for i in range(2):
v0 = np.int32(re[i*2])
v1 = np.int32(re[i*2+1])
csum = np.int32(0)
delta = np.uint32(0x9e3779b9)
for j in range(32):
csum += delta
p1 = np.int64(v1 << 4) + k2[0]
p2 = v1 + csum
uv1 = np.uint32(v1)
p3 = np.int64(uv1 >> 5) + k2[1]
v0 += np.int32(p1 ^ p2 ^ p3)
p1 = np.int64(v0 << 4) + k2[2]
p2 = v0 + csum
uv0 = np.uint32(v0)
p3 = np.int64(uv0 >> 5) + k2[3]
v1 += np.int32(p1 ^ p2 ^ p3)
re[i*2] = v0
re[i*2+1] = v1
re[0] ^= k2[2]
re[0] -= k2[2]
up = np.uint32(re[1])
re[1] = (up >> (k2[1] % 16)) | (re[1] << (32 - (k2[1] % 16)))
re[1] ^= k2[3]
up = np.uint32(re[1])
re[1] = (up >> (k2[3] % 16)) | (re[1] << (32 - (k2[3] % 16)))
up = np.uint32(re[2])
re[2] = (up >> (k2[0] % 16)) | (re[2] << (32 - (k2[0] % 16)))
re[3] -= k2[1]
re[3] ^= k2[3]
re[3] -= k2[3]
re[0] -= k2[0]
re[0] += k2[2]
up = np.uint32(re[0])
re[0] = (up >> (k2[2] % 16)) | (re[0] << (32 - (k2[2] % 16)))
up = np.uint32(re[1])
re[1] = (re[1] << (k2[1] % 16)) | (up >> (32 - (k2[1] % 16)))
re[2] += k2[0]
up = np.uint32(re[2])
re[2] = (up >> (k2[2] % 16)) | (re[2] << (32 - (k2[2] % 16)))
up = np.uint32(re[2])
re[2] = (up >> (k2[0] % 16)) | (re[2] << (32 - (k2[0] % 16)))
re[2] += k2[2]
up = np.uint32(re[2])
re[2] = (re[2] << (k2[2] % 16)) | (up >> (32 - (k2[2] % 16)))
re[3] += k2[1]
up = np.uint32(re[3])
re[3] = (re[3] << (k2[3] % 16)) | (up >> (32 - (k2[3] % 16)))
re[3] += k2[3]
up = np.uint32(re[3])
re[3] = (re[3] << (k2[3] % 16)) | (up >> (32 - (k2[3] % 16)))
hc = list('0123456789abcdef')
for i in range(len(re)):
s = ''
for j in range(4):
s += hc[(re[i] >> (j * 8 + 4)) & 15] + hc[(re[i] >> (j * 8)) & 15]
re[i] = s
re = ''.join(re)
return re
sign = douyu_sign(sys.argv[1], sys.argv[2], sys.argv[3])
print(sign)
This code works as the js code, but when I test it with the latest ub98484234 on douyu.com, I found that the algorithm already doesn't work anymore.
latest ub98484234:
ub98484234('123456', 'a9d5e814227b2f321e037c0900041501', '1551475524')
"v=220120190301&did=a9d5e814227b2f321e037c0900041501&tt=1551475524&sign=166665b8585dc8b884b38910ba4b19c5"
js:
get_sign('123456', 'a9d5e814227b2f321e037c0900041501', '1551475524')
"6141e816d610e4dc58ce4f08f67c3984"
python:
pi@raspberrypi ~ python3 douyu_sign.py 123456 a9d5e814227b2f321e037c0900041501 1551475524
roomid: 123456, did: a9d5e814227b2f321e037c0900041501, tt: 1551475524
douyu_sign.py:54: RuntimeWarning: overflow encountered in long_scalars
v1 += np.int32(p1 ^ p2 ^ p3)
douyu_sign.py:48: RuntimeWarning: overflow encountered in long_scalars
v0 += np.int32(p1 ^ p2 ^ p3)
6141e816d610e4dc58ce4f08f67c3984
Also noticed that the value of v will change over tt, it is actually some prefix with current date. 220120190301
here is the source, it is dynamic generated.
var vdwdae325w_64we = "220120190302";
If anyone familiar with decode compressed js code, it will be helpful to see what changed in the ub98484234 and find out if there is a way to implemented the working signature algorithm.
I tried change the date string according to the current timestamp, it still not work,
def douyu_sign(rid, did, tt):
print("roomid: {}, did: {}, tt: {}".format(rid, did, tt))
date = datetime.utcfromtimestamp(time.time())
time_str = '2201%d%02d%02d' % (date.year, date.month, date.day)
cb = rid + did + tt + time_str
Other parameters such as k2 also changed when the algorithm changes. The only thing I am sure that the delta remain unchanged. To make it work we need to find ways to extract the k2 from the webpage dynamically and use that k2 to update the algorithm.
I tried change the date string according to the current timestamp, it still not work,
def douyu_sign(rid, did, tt): print("roomid: {}, did: {}, tt: {}".format(rid, did, tt)) date = datetime.utcfromtimestamp(time.time()) time_str = '2201%d%02d%02d' % (date.year, date.month, date.day) cb = rid + did + tt + time_strOther parameters such as
k2also changed when the algorithm changes. The only thing I am sure that thedeltaremain unchanged. To make it work we need to find ways to extract thek2from the webpage dynamically and use thatk2to update the algorithm.
the cb's date may be related on the room last live date.
I tried change the date string according to the current timestamp, it still not work,
def douyu_sign(rid, did, tt): print("roomid: {}, did: {}, tt: {}".format(rid, did, tt)) date = datetime.utcfromtimestamp(time.time()) time_str = '2201%d%02d%02d' % (date.year, date.month, date.day) cb = rid + did + tt + time_strOther parameters such as
k2also changed when the algorithm changes. The only thing I am sure that thedeltaremain unchanged. To make it work we need to find ways to extract thek2from the webpage dynamically and use thatk2to update the algorithm.the cb's date may be related on the room last live date.
I tried another room that last stream was at 2018, the string in cb didn't work as '220120180919', the last time stream can be get from http://open.douyucdn.cn/api/RoomApi/room/+roomid
But what I've found that the returned v is exactly the current date and it has nothing to do with the tt that passed into the function.
ub98484234('6324', 'a9d5e814227b2f321e037c0900041501', '1551375524')
"v=220120190303&did=a9d5e814227b2f321e037c0900041501&tt=1551375524&sign=4d4749a1b8146f9953d50d30a71c840d"
ub98484234('6324', 'a9d5e814227b2f321e037c0900041501', '1')
"v=220120190303&did=a9d5e814227b2f321e037c0900041501&tt=1&sign=a409d5f9a0e7afe1631f267d717eb158"
ub98484234('6324', 'a9d5e814227b2f321e037c0900041501', '1000000000')
"v=220120190303&did=a9d5e814227b2f321e037c0900041501&tt=1000000000&sign=ab67da2d27c2740fd09f05e4b8e32aac"
This is my testing:
pi@raspberrypi ~ head -n 20 douyu_sign.py
import hashlib
import sys
import numpy as np
import time
from datetime import datetime
def douyu_sign(rid, did, tt):
print("roomid: {}, did: {}, tt: {}".format(rid, did, tt))
date = datetime.utcfromtimestamp(time.time())
#time_str = '2201%d%02d%02d' % (date.year, date.month, date.day)
time_str = '220120180919'
cb = rid + did + tt + time_str
print(cb)
m1 = hashlib.md5()
m1.update(cb.encode('ascii'))
rb = m1.hexdigest()
re = list()
pi@raspberrypi ~ python3 douyu_sign.py 6324 a9d5e814227b2f321e037c0900041501 1000000000
roomid: 6324, did: a9d5e814227b2f321e037c0900041501, tt: 1000000000
6324a9d5e814227b2f321e037c09000415011000000000220120180919
douyu_sign.py:55: RuntimeWarning: overflow encountered in long_scalars
v0 += np.int32(p1 ^ p2 ^ p3)
douyu_sign.py:61: RuntimeWarning: overflow encountered in long_scalars
v1 += np.int32(p1 ^ p2 ^ p3)
2bc98bca03c952211012b0e409a83cd7
So basically we only know v is the current date, we need to find out how algorithms change over time. IMO the current date string time_str plus some changing k2 has high probability.
I tried change the date string according to the current timestamp, it still not work,
def douyu_sign(rid, did, tt): print("roomid: {}, did: {}, tt: {}".format(rid, did, tt)) date = datetime.utcfromtimestamp(time.time()) time_str = '2201%d%02d%02d' % (date.year, date.month, date.day) cb = rid + did + tt + time_strOther parameters such as
k2also changed when the algorithm changes. The only thing I am sure that thedeltaremain unchanged. To make it work we need to find ways to extract thek2from the webpage dynamically and use thatk2to update the algorithm.the cb's date may be related on the room last live date.
I tried another room that last stream was at 2018, the string in
cbdidn't work as '220120180919', the last time stream can be get from http://open.douyucdn.cn/api/RoomApi/room/+roomid
But what I've found that the returnedvis exactly the current date and it has nothing to do with the tt that passed into the function.ub98484234('6324', 'a9d5e814227b2f321e037c0900041501', '1551375524') "v=220120190303&did=a9d5e814227b2f321e037c0900041501&tt=1551375524&sign=4d4749a1b8146f9953d50d30a71c840d" ub98484234('6324', 'a9d5e814227b2f321e037c0900041501', '1') "v=220120190303&did=a9d5e814227b2f321e037c0900041501&tt=1&sign=a409d5f9a0e7afe1631f267d717eb158" ub98484234('6324', 'a9d5e814227b2f321e037c0900041501', '1000000000') "v=220120190303&did=a9d5e814227b2f321e037c0900041501&tt=1000000000&sign=ab67da2d27c2740fd09f05e4b8e32aac"This is my testing:
pi@raspberrypi ~ head -n 20 douyu_sign.py import hashlib import sys import numpy as np import time from datetime import datetime def douyu_sign(rid, did, tt): print("roomid: {}, did: {}, tt: {}".format(rid, did, tt)) date = datetime.utcfromtimestamp(time.time()) #time_str = '2201%d%02d%02d' % (date.year, date.month, date.day) time_str = '220120180919' cb = rid + did + tt + time_str print(cb) m1 = hashlib.md5() m1.update(cb.encode('ascii')) rb = m1.hexdigest() re = list() pi@raspberrypi ~ python3 douyu_sign.py 6324 a9d5e814227b2f321e037c0900041501 1000000000 roomid: 6324, did: a9d5e814227b2f321e037c0900041501, tt: 1000000000 6324a9d5e814227b2f321e037c09000415011000000000220120180919 douyu_sign.py:55: RuntimeWarning: overflow encountered in long_scalars v0 += np.int32(p1 ^ p2 ^ p3) douyu_sign.py:61: RuntimeWarning: overflow encountered in long_scalars v1 += np.int32(p1 ^ p2 ^ p3) 2bc98bca03c952211012b0e409a83cd7So basically we only know
vis the current date, we need to find out how algorithms change over time. IMO the current date stringtime_strplus some changingk2has high probability.
By comparing the https://www.douyu.com/swf_api/homeH5Enc?rids={RoomID} js of different room ids, it seems that the encryption algorithm of each room is different(not only k2 and v), so the current API can only get js and run it to decrypt the sign.
Can anyone provide another API?
```//length = 368
var f3 = [0x5cc389d8,0x89983bc0,0xb012db12,0x7932753b,0xd6c5b89,0x686a6c3a,0xecad9860,0x95654458,0x719096a4,0x587aaac6,0x74e3f61,0xcb466b6b,0xc8c64e18,0xf71e1e9c,0x785cb639,0x9fb3d17a,0x399f3ea5,0xdf9d92e8,0x32e9eb35,0x6576219b,0xc9402c8f,0xfff8dded,0x756fa883,0x62ddffd5,0x9ff27712,0xa8e0b421,0xc245cf71,0x898ad7ae,0x440c1a3d,0x2a653c8,0x6df3ca8f,0xb74de679,0x7c8d6fa0,0x5b408cce,0xb78b28cd,0x303ac85c,0x981707f9,0x59e24b6e,0xae5a8b16,0xafda5d1,0x39136686,0xf11b886f,0xb8e7317d,0x1c656003,0x33d85f4f,0x769c3c28,0x19a77d4,0x9f0c9108,0xab7b824b,0x5e3ac610,0x7bb5c682,0x27cc0431,0x4926e9dc,0x8973eb43,0x179c2f77,0x3d8e6861,0xd1f003a,0xa938e112,0x9c44d6ae,0x22b826d,0xeb940d5c,0x75c370e5,0xfe50872d,0xe316311b,0x806cb693,0xd552d48f,0x1fb98fb2,0x10b8ea91,0x8fa0699f,0x45f14179,0x3648e3b6,0x7f45f821,0x5585d3a0,0xe539ef80,0x36202d52,0x9112a027,0xdcea463b,0xad6aac8b,0xbd5bc4f4,0xbe230f6f,0xa7805c53,0x775e1160,0x45f997eb,0xa1415ef2,0xe664546f,0x4f67484f,0x4d914e24,0xec0b1137,0xb8a1573d,0x4bd509c2,0x3baf6130,0x4d0a3540,0x92258389,0x2ae18862,0x5316e722,0xa3adecaf,0x1a333b36,0xc86404a5,0xbe63b2d0,0x2870a1e0,0xf52612fb,0xa2c824fb,0x9924e3f0,0x76748ae,0x2fa9d945,0x20023551,0xe36c0f3f,0xd9fc9d73,0xb356a4c3,0x7e674c64,0x404276ac,0x7760d764,0x37c99e03,0x824f959d,0x85511212,0xe740d8e8,0x8d1f680,0x5c14356c,0xfa448b46,0x644b3c75,0x7b98107d,0x258ce73f,0x98ad3bef,0x6ae20b5b,0x1021af03,0xf2b092dc,0xb439f17c,0x53e81464,0x8471dc9,0x965a689c,0x3615b95c,0x1fff43f0,0x469eff63,0xa9678bf0,0x1b08fa6f,0x1bd106e2,0x90254256,0x31e53e56,0xf3f3dbfb,0x82c88f92,0xf09d989e,0xeb61e887,0xf4cd2f05,0x8b0c5704,0xa6419cca,0xaf12eac8,0xbb8e609c,0x386b3aea,0x24ad0766,0x152c1ac3,0x65abc188,0x86fd7c68,0x653ed4ea,0x7864a3e,0xe622e0b3,0xa6f04397,0xc6287931,0xad2b881a,0x25f80785,0x34420262,0x6c0c432c,0x986a6a32,0xd95d8ac4,0xaec6c8b5,0x2e2a86b,0x6621c8db,0x3a5b6266,0x7085d2ae,0x2b6c9363,0xbac3035a,0x6cbd8457,0xea4ceea9,0x19e8a2a5,0xc6d11a4,0x5a515ade,0x8756dac6,0x520b5f41,0xb2814f3,0x2697890b,0x2a24d1ee,0xe5c9b47a,0x4cf0d0e,0x5e008ab,0x61bbf8e0,0x21681c16,0x17f0550c,0xa1d4bdcc,0x90bf06af,0xedb06a60,0x9f034f1,0x71b3c15f,0x87e106d9,0xa61afc0f,0xb0e8478d,0x478b939a,0x72ab2ea0,0x6f8bccc7,0x44a595b9,0x2f788bd5,0xfc9a3222,0x9f5f956c,0x31a21055,0x7b54be72,0x91f599a3,0x7f6f811f,0x91dcb611,0x80916dd4,0x9b4718cd,0x6caf74f3,0x485e0eae,0x64c4f0e1,0xc56f7668,0x33924838,0x5ec9c6ec,0xc84f57fd,0x6defbea1,0x1e9cd613,0x8b276a43,0x7cd0b0c0,0x5cd40f74,0xa20ff79a,0xd4ae260b,0x30eef7d9,0x298907f6,0x66696d98,0x3cbe6e65,0x4a14b41d,0xc6ddb8b5,0xffa97ed2,0x8f59728d,0xd825a6f8,0x5f95d778,0x3d0806c3,0x395b69a9,0x3543bf75,0x9b0169f5,0xe88af13d,0x2e5682c8,0x9aa11f9e,0xfa0a3253,0x89a2e899,0x926cf928,0xa187d19d,0x4f681a68,0x57f3a4ed,0xaa1241b7,0x75347c7b,0xbe239450,0xf07736de,0xaba78b24,0x8263ed5f,0x1121275c,0xc30df998,0x66a6eb44,0xdb703d53,0x53f93cf9,0x7575eebe,0xbbfafbd8,0x3132ec71,0xbc2af3ff,0xc3ecd327,0x7259e92a,0x262a99bf,0x486644e3,0x5a9de2a1,0xa8d3a21e,0x5e030123,0xb87d1178,0xb335a7f0,0x23569ed4,0xb91316b7,0x7a0af8e1,0x3b186e62,0x8c074317,0x75f6a91d,0x22beea17,0xd53cd8db,0xade253a,0xdc000255,0x1101797b,0x490d5e5e,0x76324bc2,0x77f8f551,0x9e112647,0xcb175aed,0x4f5fb6cd,0x46014745,0xb999dd24,0x8b658d8,0x688e8456,0x38be6404,0x1f6cfd8,0x52808fa,0xd8459ff4,0x5e6d008c,0x4a1d87c7,0x891d18f9,0x794ee16a,0x4048930c,0xba48818a,0x5cc0eec0,0xf89b8d65,0x76dc8c7f,0x2605f404,0xf1719d4a,0xacf1f398,0xc4459281,0x8781edfc,0xd62101c6,0x28d138d6,0xc4bce54b,0xf073354a,0x317094a0,0x862cbda9,0xc45661b2,0x230e1735,0xc32f50b7,0xfd252d43,0x44dd8e18,0x32a9669c,0xc3c24680,0xd6a0a593,0xab619393,0x1ad5c8cd,0x2133b73,0x9daa213e,0x36132a22,0x8f9e7b0d,0x4d066c4b,0x25d9a264,0x33fd5b73,0xe75b65c5,0x47168d1d,0xe4e8f6ea,0x50669295,0x880d87bb,0xa70d3f77,0x67319089,0xe23349f3,0x3a528b3a,0xa47f314a,0x12be7a10,0x5885d10b,0x763a2082,0x25cea653,0x51b2151f,0x69be950e,0xa6f977fe,0x36a4e45c,0xd7436e22,0x70bf8ff,0xdff77d3b,0xc01143d1,0x5e5fa18e,0xb34827c5,0x9153473d,0x6e4228fd,0x86cfec0b,0x53369a98,0x4e775d7f,0x8bb2751a,0x3e73b9f3,0xa11bc3cb,0x59c07e58,0x66c9ff6b,0xa683b2ce,0xeb85e66a,0x9d6fa21];
function get_sign(p1, p2, p3){
/*
//length = 184
var rk=[
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28
];
*/
var r_key = [27, 18, 27, 28, 10, 32, 40, 31, 10];
var rk = [];
for(var i = 0; i < f3.length / 2; i++){
rk[i] = r_key[i % 9]
}
var k2=[0x47fa3eef,0x209ff543];
var lk=k2;
var v = f3.slice(0);
var k=[0x3bbe6784,0x6cd672ae,0x96496df1,0xbfe901eb];
for(var O=0; O < f3.length; O++){
v[O]^=0x405ca50f;
}
var i = 1;
var counter = 1;
while(i < v.length){
if(i % 2)
v[i] += k2[1];
else//i % 2 == 0
v[i] += k2[0];
if(counter<2){
i+=5;
counter++;
}
else if(counter == 2){
i+=8;
counter=0;
}
}
v[0]^=lk[0];//5
v[7]^=lk[1];//2
v[9]^=lk[1];//2
v[11]^=lk[1];//2
v[13]^=lk[1];//2
v[18]^=lk[0];//7
v[25]^=lk[1];//2
v[27]^=lk[1];//2
v[29]^=lk[1];//2
v[31]^=lk[1];//5
v[36]^=lk[0];//7
v[43]^=lk[1];//2
v[45]^=lk[1];//2
v[47]^=lk[1];//2
v[49]^=lk[1];//5
v[54]^=lk[0];//7
v[61]^=lk[1];//2
v[63]^=lk[1];//2
v[65]^=lk[1];//2
v[67]^=lk[1];//5
v[72]^=lk[0];//7
v[79]^=lk[1];//2
v[81]^=lk[1];//2
v[83]^=lk[1];//2
v[85]^=lk[1];//5
v[90]^=lk[0];
v[97]^=lk[1];
v[99]^=lk[1];
v[101]^=lk[1];
v[103]^=lk[1];
v[108]^=lk[0];
v[115]^=lk[1];
v[117]^=lk[1];
v[119]^=lk[1];
v[121]^=lk[1];
v[126]^=lk[0];
v[133]^=lk[1];
v[135]^=lk[1];
v[137]^=lk[1];
v[139]^=lk[1];
v[144]^=lk[0];
v[151]^=lk[1];
v[153]^=lk[1];
v[155]^=lk[1];
v[157]^=lk[1];
v[162]^=lk[0];
v[169]^=lk[1];
v[171]^=lk[1];
v[173]^=lk[1];
v[175]^=lk[1];
v[180]^=lk[0];
v[187]^=lk[1];
v[189]^=lk[1];
v[3]=(v[3]<<(lk[1]%16))|(v[3]>>>(32-(lk[1]%16)));
v[2]=(v[2]>>>(lk[0]%16))|(v[2]<<(32-(lk[0]%16)));
v[5]=(v[5]<<(lk[1]%16))|(v[5]>>>(32-(lk[1]%16)));
v[4]-=lk[0];
v[8]-=lk[0];
v[10]=(v[10]<<(lk[0]%16))|(v[10]>>>(32-(lk[0]%16)));
v[12]-=lk[0];
v[15]=(v[15]<<(lk[1]%16))|(v[15]>>>(32-(lk[1]%16)));
v[17]-=lk[1];
v[16]-=lk[0];
v[21]=(v[21]<<(lk[1]%16))|(v[21]>>>(32-(lk[1]%16)));
v[20]=(v[20]>>>(lk[0]%16))|(v[20]<<(32-(lk[0]%16)));
v[23]=(v[23]<<(lk[1]%16))|(v[23]>>>(32-(lk[1]%16)));
v[22]-=lk[0];
v[26]-=lk[0];
v[28]=(v[28]<<(lk[0]%16))|(v[28]>>>(32-(lk[0]%16)));
v[30]-=lk[0];
v[33]=(v[33]<<(lk[1]%16))|(v[33]>>>(32-(lk[1]%16)));
v[35]-=lk[1];
v[34]-=lk[0];
v[39]=(v[39]<<(lk[1]%16))|(v[39]>>>(32-(lk[1]%16)));
v[38]=(v[38]>>>(lk[0]%16))|(v[38]<<(32-(lk[0]%16)));
v[41]=(v[41]<<(lk[1]%16))|(v[41]>>>(32-(lk[1]%16)));
v[40]-=lk[0];
v[44]-=lk[0];
v[46]=(v[46]<<(lk[0]%16))|(v[46]>>>(32-(lk[0]%16)));
v[48]-=lk[0];
v[51]=(v[51]<<(lk[1]%16))|(v[51]>>>(32-(lk[1]%16)));
v[53]-=lk[1];
v[52]-=lk[0];
v[57]=(v[57]<<(lk[1]%16))|(v[57]>>>(32-(lk[1]%16)));
v[56]=(v[56]>>>(lk[0]%16))|(v[56]<<(32-(lk[0]%16)));
v[59]=(v[59]<<(lk[1]%16))|(v[59]>>>(32-(lk[1]%16)));
v[58]-=lk[0];
v[62]-=lk[0];
v[64]=(v[64]<<(lk[0]%16))|(v[64]>>>(32-(lk[0]%16)));
v[66]-=lk[0];
v[69]=(v[69]<<(lk[1]%16))|(v[69]>>>(32-(lk[1]%16)));
v[71]-=lk[1];
v[70]-=lk[0];
v[75]=(v[75]<<(lk[1]%16))|(v[75]>>>(32-(lk[1]%16)));
v[74]=(v[74]>>>(lk[0]%16))|(v[74]<<(32-(lk[0]%16)));
v[77]=(v[77]<<(lk[1]%16))|(v[77]>>>(32-(lk[1]%16)));
v[76]-=lk[0];
v[80]-=lk[0];
v[82]=(v[82]<<(lk[0]%16))|(v[82]>>>(32-(lk[0]%16)));
v[84]-=lk[0];
v[87]=(v[87]<<(lk[1]%16))|(v[87]>>>(32-(lk[1]%16)));
v[89]-=lk[1];
v[88]-=lk[0];
v[93]=(v[93]<<(lk[1]%16))|(v[93]>>>(32-(lk[1]%16)));
v[92]=(v[92]>>>(lk[0]%16))|(v[92]<<(32-(lk[0]%16)));
v[95]=(v[95]<<(lk[1]%16))|(v[95]>>>(32-(lk[1]%16)));
v[94]-=lk[0];
v[98]-=lk[0];
v[100]=(v[100]<<(lk[0]%16))|(v[100]>>>(32-(lk[0]%16)));
v[102]-=lk[0];
v[105]=(v[105]<<(lk[1]%16))|(v[105]>>>(32-(lk[1]%16)));
v[107]-=lk[1];
v[106]-=lk[0];
v[111]=(v[111]<<(lk[1]%16))|(v[111]>>>(32-(lk[1]%16)));
v[110]=(v[110]>>>(lk[0]%16))|(v[110]<<(32-(lk[0]%16)));
v[113]=(v[113]<<(lk[1]%16))|(v[113]>>>(32-(lk[1]%16)));
v[112]-=lk[0];
v[116]-=lk[0];
v[118]=(v[118]<<(lk[0]%16))|(v[118]>>>(32-(lk[0]%16)));
v[120]-=lk[0];
v[123]=(v[123]<<(lk[1]%16))|(v[123]>>>(32-(lk[1]%16)));
v[125]-=lk[1];
v[124]-=lk[0];
v[129]=(v[129]<<(lk[1]%16))|(v[129]>>>(32-(lk[1]%16)));
v[128]=(v[128]>>>(lk[0]%16))|(v[128]<<(32-(lk[0]%16)));
v[131]=(v[131]<<(lk[1]%16))|(v[131]>>>(32-(lk[1]%16)));
v[130]-=lk[0];
v[134]-=lk[0];
v[136]=(v[136]<<(lk[0]%16))|(v[136]>>>(32-(lk[0]%16)));
v[138]-=lk[0];
v[141]=(v[141]<<(lk[1]%16))|(v[141]>>>(32-(lk[1]%16)));
v[143]-=lk[1];
v[142]-=lk[0];
v[147]=(v[147]<<(lk[1]%16))|(v[147]>>>(32-(lk[1]%16)));
v[146]=(v[146]>>>(lk[0]%16))|(v[146]<<(32-(lk[0]%16)));
v[149]=(v[149]<<(lk[1]%16))|(v[149]>>>(32-(lk[1]%16)));
v[148]-=lk[0];
v[152]-=lk[0];
v[154]=(v[154]<<(lk[0]%16))|(v[154]>>>(32-(lk[0]%16)));
v[156]-=lk[0];
v[159]=(v[159]<<(lk[1]%16))|(v[159]>>>(32-(lk[1]%16)));
v[161]-=lk[1];
v[160]-=lk[0];
v[165]=(v[165]<<(lk[1]%16))|(v[165]>>>(32-(lk[1]%16)));
v[164]=(v[164]>>>(lk[0]%16))|(v[164]<<(32-(lk[0]%16)));
v[167]=(v[167]<<(lk[1]%16))|(v[167]>>>(32-(lk[1]%16)));
v[166]-=lk[0];
v[170]-=lk[0];
v[172]=(v[172]<<(lk[0]%16))|(v[172]>>>(32-(lk[0]%16)));
v[174]-=lk[0];
v[177]=(v[177]<<(lk[1]%16))|(v[177]>>>(32-(lk[1]%16)));
v[179]-=lk[1];
v[178]-=lk[0];
v[183]=(v[183]<<(lk[1]%16))|(v[183]>>>(32-(lk[1]%16)));
v[182]=(v[182]>>>(lk[0]%16))|(v[182]<<(32-(lk[0]%16)));
v[185]=(v[185]<<(lk[1]%16))|(v[185]>>>(32-(lk[1]%16)));
v[184]-=lk[0];
v[188]-=lk[0];
v[191]^=lk[1];
v[190]=(v[190]<<(lk[0]%16))|(v[190]>>>(32-(lk[0]%16)));
v[193]^=lk[1];
v[192]-=lk[0];
v[195]=(v[195]<<(lk[1]%16))|(v[195]>>>(32-(lk[1]%16)));
v[197]-=lk[1];
v[196]-=lk[0];
v[198]^=lk[0];
v[201]=(v[201]<<(lk[1]%16))|(v[201]>>>(32-(lk[1]%16)));
v[200]=(v[200]>>>(lk[0]%16))|(v[200]<<(32-(lk[0]%16)));
v[203]=(v[203]<<(lk[1]%16))|(v[203]>>>(32-(lk[1]%16)));
v[202]-=lk[0];
v[205]^=lk[1];
v[207]^=lk[1];
v[206]-=lk[0];
v[209]^=lk[1];
v[208]=(v[208]<<(lk[0]%16))|(v[208]>>>(32-(lk[0]%16)));
v[211]^=lk[1];
v[210]-=lk[0];
v[213]=(v[213]<<(lk[1]%16))|(v[213]>>>(32-(lk[1]%16)));
v[215]-=lk[1];
v[214]-=lk[0];
v[216]^=lk[0];
v[219]=(v[219]<<(lk[1]%16))|(v[219]>>>(32-(lk[1]%16)));
v[218]=(v[218]>>>(lk[0]%16))|(v[218]<<(32-(lk[0]%16)));
v[221]=(v[221]<<(lk[1]%16))|(v[221]>>>(32-(lk[1]%16)));
v[220]-=lk[0];
v[223]^=lk[1];
v[225]^=lk[1];
v[224]-=lk[0];
v[227]^=lk[1];
v[226]=(v[226]<<(lk[0]%16))|(v[226]>>>(32-(lk[0]%16)));
v[229]^=lk[1];
v[228]-=lk[0];
v[231]=(v[231]<<(lk[1]%16))|(v[231]>>>(32-(lk[1]%16)));
v[233]-=lk[1];
v[232]-=lk[0];
v[234]^=lk[0];
v[237]=(v[237]<<(lk[1]%16))|(v[237]>>>(32-(lk[1]%16)));
v[236]=(v[236]>>>(lk[0]%16))|(v[236]<<(32-(lk[0]%16)));
v[239]=(v[239]<<(lk[1]%16))|(v[239]>>>(32-(lk[1]%16)));
v[238]-=lk[0];
v[241]^=lk[1];
v[243]^=lk[1];
v[242]-=lk[0];
v[245]^=lk[1];
v[244]=(v[244]<<(lk[0]%16))|(v[244]>>>(32-(lk[0]%16)));
v[247]^=lk[1];
v[246]-=lk[0];
v[249]=(v[249]<<(lk[1]%16))|(v[249]>>>(32-(lk[1]%16)));
v[251]-=lk[1];
v[250]-=lk[0];
v[252]^=lk[0];
v[255]=(v[255]<<(lk[1]%16))|(v[255]>>>(32-(lk[1]%16)));
v[254]=(v[254]>>>(lk[0]%16))|(v[254]<<(32-(lk[0]%16)));
v[257]=(v[257]<<(lk[1]%16))|(v[257]>>>(32-(lk[1]%16)));
v[256]-=lk[0];
v[259]^=lk[1];
v[261]^=lk[1];
v[260]-=lk[0];
v[263]^=lk[1];
v[262]=(v[262]<<(lk[0]%16))|(v[262]>>>(32-(lk[0]%16)));
v[265]^=lk[1];
v[264]-=lk[0];
v[267]=(v[267]<<(lk[1]%16))|(v[267]>>>(32-(lk[1]%16)));
v[269]-=lk[1];
v[268]-=lk[0];
v[270]^=lk[0];
v[273]=(v[273]<<(lk[1]%16))|(v[273]>>>(32-(lk[1]%16)));
v[272]=(v[272]>>>(lk[0]%16))|(v[272]<<(32-(lk[0]%16)));
v[275]=(v[275]<<(lk[1]%16))|(v[275]>>>(32-(lk[1]%16)));
v[274]-=lk[0];
v[277]^=lk[1];
v[279]^=lk[1];
v[278]-=lk[0];
v[281]^=lk[1];
v[280]=(v[280]<<(lk[0]%16))|(v[280]>>>(32-(lk[0]%16)));
v[283]^=lk[1];
v[282]-=lk[0];
v[285]=(v[285]<<(lk[1]%16))|(v[285]>>>(32-(lk[1]%16)));
v[287]-=lk[1];
v[286]-=lk[0];
v[288]^=lk[0];
v[291]=(v[291]<<(lk[1]%16))|(v[291]>>>(32-(lk[1]%16)));
v[290]=(v[290]>>>(lk[0]%16))|(v[290]<<(32-(lk[0]%16)));
v[293]=(v[293]<<(lk[1]%16))|(v[293]>>>(32-(lk[1]%16)));
v[292]-=lk[0];
v[295]^=lk[1];
v[297]^=lk[1];
v[296]-=lk[0];
v[299]^=lk[1];
v[298]=(v[298]<<(lk[0]%16))|(v[298]>>>(32-(lk[0]%16)));
v[301]^=lk[1];
v[300]-=lk[0];
v[303]=(v[303]<<(lk[1]%16))|(v[303]>>>(32-(lk[1]%16)));
v[305]-=lk[1];
v[304]-=lk[0];
v[306]^=lk[0];
v[309]=(v[309]<<(lk[1]%16))|(v[309]>>>(32-(lk[1]%16)));
v[308]=(v[308]>>>(lk[0]%16))|(v[308]<<(32-(lk[0]%16)));
v[311]=(v[311]<<(lk[1]%16))|(v[311]>>>(32-(lk[1]%16)));
v[310]-=lk[0];
v[313]^=lk[1];
v[315]^=lk[1];
v[314]-=lk[0];
v[317]^=lk[1];
v[316]=(v[316]<<(lk[0]%16))|(v[316]>>>(32-(lk[0]%16)));
v[319]^=lk[1];
v[318]-=lk[0];
v[321]=(v[321]<<(lk[1]%16))|(v[321]>>>(32-(lk[1]%16)));
v[323]-=lk[1];
v[322]-=lk[0];
v[324]^=lk[0];
v[327]=(v[327]<<(lk[1]%16))|(v[327]>>>(32-(lk[1]%16)));
v[326]=(v[326]>>>(lk[0]%16))|(v[326]<<(32-(lk[0]%16)));
v[329]=(v[329]<<(lk[1]%16))|(v[329]>>>(32-(lk[1]%16)));
v[328]-=lk[0];
v[331]^=lk[1];
v[333]^=lk[1];
v[332]-=lk[0];
v[335]^=lk[1];
v[334]=(v[334]<<(lk[0]%16))|(v[334]>>>(32-(lk[0]%16)));
v[337]^=lk[1];
v[336]-=lk[0];
v[339]=(v[339]<<(lk[1]%16))|(v[339]>>>(32-(lk[1]%16)));
v[341]-=lk[1];
v[340]-=lk[0];
v[342]^=lk[0];
v[345]=(v[345]<<(lk[1]%16))|(v[345]>>>(32-(lk[1]%16)));
v[344]=(v[344]>>>(lk[0]%16))|(v[344]<<(32-(lk[0]%16)));
v[347]=(v[347]<<(lk[1]%16))|(v[347]>>>(32-(lk[1]%16)));
v[346]-=lk[0];
v[349]^=lk[1];
v[351]^=lk[1];
v[350]-=lk[0];
v[353]^=lk[1];
v[352]=(v[352]<<(lk[0]%16))|(v[352]>>>(32-(lk[0]%16)));
v[355]^=lk[1];
v[354]-=lk[0];
v[357]=(v[357]<<(lk[1]%16))|(v[357]>>>(32-(lk[1]%16)));
v[359]-=lk[1];
v[358]-=lk[0];
v[360]^=lk[0];
v[363]=(v[363]<<(lk[1]%16))|(v[363]>>>(32-(lk[1]%16)));
v[362]=(v[362]>>>(lk[0]%16))|(v[362]<<(32-(lk[0]%16)));
v[365]=(v[365]<<(lk[1]%16))|(v[365]>>>(32-(lk[1]%16)));
v[364]-=lk[0];
v[367]^=lk[1];
for(var I=0; I<368; I+=2){
var i,
v0=v[I]^k2[0],
v1=v[I+1]^k2[1],
d=0x9E3779B9,
sum=d*rk[I/2];
for(i=0; i<rk[I/2]; i++){
v1-=(((v0<<4)^(v0>>>5))+v0)^(sum+k[(sum>>>11)&3]);
sum-=d;
v0-=(((v1<<4)^(v1>>>5))+v1)^(sum+k[sum&3]);
}
v[I]=v0^k2[1];
v[I+1]=v1^k2[0];
}
for(var O=367; O>0; O--){
v[O]^=v[O-1];
}
v[0]^=0x405ca50f;
var strc="";
for(var i=0; i<v.length; i++) {
strc+=String.fromCharCode(v[i]&0xff,v[i]>>>8&0xff,v[i]>>>16&0xff,v[i]>>>24&0xff);
}
return strc;
}
this is the function in https://www.douyu.com/swf_api/homeH5Enc?rids=6324 that was used to generate the js code.
get_sign('241432', 'c0ed4bd228dd366ecaf6b94200041501', '1551457047')
"(function (xx0,xx1,xx2){var cb=xx0+xx1+xx2+"220120180919";var rb=CryptoJS.MD5(cb).toString();var re=[];for(var i=0;i
The `f3` is the encrypted js code, each 8 byte value represent a 4 char code. Those bit operations and there are four decryption steps in this algorithm.
The first decryption key is `0x405ca50f` in this example, you can decrypt the data by simple XOR operation like
for(var O=0; O < f3.length; O++){
v[O]^=0x405ca50f;
}
The second decryption key is two 32 bit hex values, `k2=[0x47fa3eef,0x209ff543]`.
For every element in the decrypted list there are bit operations using the `k2`, those operations are dynamic, different from each other. But elements are independent, you can decode the parts that you want without decoding the whole data. If we want to decode the data by this algorithm, we need to dynamic analysis those instructions by python.
The third decryption key is a list with 4 keys. `k=[0x3bbe6784,0x6cd672ae,0x96496df1,0xbfe901eb]` in the example. The algorithm decode the data with a fixed delta key and the providing key `k`.
The forth decryption algorithm is to xor values inversely for the data list. Then set the element at index 0 to 0x405ca50f.
After all, iterate the list, for each element the plaintext it contains from low bits to high bits, decoded by
for(var i=0; i
}
```
The hard part is to get the dynamic bit operation code and get it run in python. Once get that done the remaining part is not so difficult.
I think use javascript interpreter is the best choice,
and ykdl already implemented it:
https://github.com/zhangn1985/ykdl/blob/master/ykdl/util/jsengine.py
https://github.com/zhangn1985/ykdl/blob/master/ykdl/extractors/douyu/live.py
I think use javascript interpreter is the best choice,
and ykdl already implemented it:
https://github.com/zhangn1985/ykdl/blob/master/ykdl/util/jsengine.py
https://github.com/zhangn1985/ykdl/blob/master/ykdl/extractors/douyu/live.py
可以看这里,他们基本跑通了js注入方式,只要再装个nodejs 😂😂😂,返回流地址接口完全可用。
如投入实用还需要在
https://github.com/zhangn1985/ykdl/blob/1359e955beeef315e5bfb36a329bf1a007735188/ykdl/util/jsengine.py#L95
之上加一行:
exports = undefined;
另外,对应格式还需要改几个bug,看来斗鱼这次增加了不少可选流质量。
https://github.com/zhangn1985/ykdl/issues/376#issuecomment-469308476
https://github.com/zhangn1985/ykdl/issues/378#issuecomment-469263903
我提供另外1个思路:
首页的预览功能:https://playweb.douyucdn.cn/lapi/live/hlsH5Preview/{roomid}
同样需要加密,不过解密比较简单,和之前一样。而且auth貌似可以重复用,只需每次修改post的roomid就行了。
可以得到这样的内容:
{"error":0,"msg":"success","data":{"room_id":73440,"rtmp_cdn":"","rtmp_url":"https://hlsa.douyucdn.cn/live","rtmp_live":"73440rnreveCzTPB_550/playlist.m3u8?wsSecret=2645c3ead696b918af891de332a0f783\u0026wsTime=1551724300\u0026token=web-douyu-0-73440-86a8d06a5e2d3fbacfc6d18b59215a5a\u0026did=a1eae6d57d995b322fe5fd9000061501\u0026ver=2018061203\u0026st=0\u0026preview=1\u0026pt=3","client_ip":"115.192.209.72","cdnsWithName":null,"multirates":null,"is_pass_player":0}}
问题是得到的视频是550p的,更改后缀后无效。
不过m3u8格式的的封装比较简单,访问m3u8的链接:
https://hlsa.douyucdn.cn/live/73440rnreveCzTPB_550/playlist.m3u8?wsSecret=2645c3ead696b918af891de332a0f783&wsTime=1551724300&token=web-douyu-0-73440-86a8d06a5e2d3fbacfc6d18b59215a5a&did=a1eae6d57d995b322fe5fd9000061501&ver=2018061203&st=0&preview=1&pt=3
,得到这个内容:
EXTM3U
EXT-X-VERSION:3
EXT-X-ALLOW-CACHE:NO
EXT-X-TARGETDURATION:3
EXT-X-MEDIA-SEQUENCE:1551717280
EXTINF:2.990,
1551717279.ts?wsApp=HLS&wsMonitor=0
EXTINF:2.985,
1551717280.ts?wsApp=HLS&wsMonitor=0
EXTINF:2.981,
1551717281.ts?wsApp=HLS&wsMonitor=0
然后浏览器访问地址是类似这样的:
https://hlsa.douyucdn.cn/live/73440rnreveCzTPB_550/1551717279.ts?wsApp=HLS&wsMonitor=0
我们可以去掉_500.得到的地址:
https://hlsa.douyucdn.cn/live/73440rnreveCzTPB/1551717279.ts
这样的地址是无限制访问的,不知道这有没有帮助
Can we keep it in English please?
This is an international project / issue tracker and not a Chinese one, even if this issue is about a Chinese streaming site.
@leis1015 这应该是流媒体服务器漏洞,可以深入研究,前几年有人也提过。
没搞起来,一方面要做播放器hack,更可能还是怕斗鱼封IP吧😇😇😇
我提供另外1个思路:
首页的预览功能:https://playweb.douyucdn.cn/lapi/live/hlsH5Preview/{roomid}
同样需要加密,不过解密比较简单,和之前一样。而且auth貌似可以重复用,只需每次修改post的roomid就行了。
可以得到这样的内容:{"error":0,"msg":"success","data":{"room_id":73440,"rtmp_cdn":"","rtmp_url":"https://hlsa.douyucdn.cn/live","rtmp_live":"73440rnreveCzTPB_550/playlist.m3u8?wsSecret=2645c3ead696b918af891de332a0f783\u0026wsTime=1551724300\u0026token=web-douyu-0-73440-86a8d06a5e2d3fbacfc6d18b59215a5a\u0026did=a1eae6d57d995b322fe5fd9000061501\u0026ver=2018061203\u0026st=0\u0026preview=1\u0026pt=3","client_ip":"115.192.209.72","cdnsWithName":null,"multirates":null,"is_pass_player":0}}
问题是得到的视频是550p的,更改后缀后无效。
不过m3u8格式的的封装比较简单,访问m3u8的链接:
https://hlsa.douyucdn.cn/live/73440rnreveCzTPB_550/playlist.m3u8?wsSecret=2645c3ead696b918af891de332a0f783&wsTime=1551724300&token=web-douyu-0-73440-86a8d06a5e2d3fbacfc6d18b59215a5a&did=a1eae6d57d995b322fe5fd9000061501&ver=2018061203&st=0&preview=1&pt=3
,得到这个内容:EXTM3U
EXT-X-VERSION:3
EXT-X-ALLOW-CACHE:NO
EXT-X-TARGETDURATION:3
EXT-X-MEDIA-SEQUENCE:1551717280
EXTINF:2.990,
1551717279.ts?wsApp=HLS&wsMonitor=0
EXTINF:2.985,
1551717280.ts?wsApp=HLS&wsMonitor=0
EXTINF:2.981,
1551717281.ts?wsApp=HLS&wsMonitor=0
然后浏览器访问地址是类似这样的:
https://hlsa.douyucdn.cn/live/73440rnreveCzTPB_550/1551717279.ts?wsApp=HLS&wsMonitor=0
我们可以去掉_500.得到的地址:
https://hlsa.douyucdn.cn/live/73440rnreveCzTPB/1551717279.ts
这样的地址是无限制访问的,不知道这有没有帮助
That HLS API works but after about 5 minutes it will disconnect. You can see discussion here https://github.com/spacemeowx2/DouyuHTML5Player/issues/28
seated and waiting for problem solved
[cli][debug] OS: Linux-4.15.0-48-generic-x86_64-with-Ubuntu-18.04-bionic
[cli][debug] Python: 3.6.7
[cli][debug] Streamlink: 1.1.0
[cli][debug] Requests(2.18.4), Socks(1.6.5), Websocket(0.44.0)
[cli][info] Found matching plugin douyutv for URL https://www.douyu.com/8733
error: Unable to open URL: https://capi.douyucdn.cn/api/v1/room/8733?aid=wp&cdn=ws&client_sys=wp&time=1556896493&auth=717f5d05496fbc077a7b8070662a01d6 (401 Client Error: Unauthorized for url: https://capi.douyucdn.cn/api/v1/room/8733?aid=wp&cdn=ws&client_sys=wp&time=1556896493&auth=717f5d05496fbc077a7b8070662a01d6)
提供一个思路,我用kali获取了手机上斗鱼直播的url地址,可以访问,也是flv格式。不过似乎加密了,打开流画面绿色,声音断断续续。但在我手机保持十分钟连接后,可用!
附上链接:
http://112.29.203.132/hdla.douyucdn.cn/live/2550505rQ61Zn1Ob.flv?wsAuth=d7bef22ed2913956e9091e9076009da5&token=cpn-androidfapp-0-2550505-77d6eaf57354c9a988bbe73562ac9e9921ae1c50956265ea&logo=0&expire=0&did=2e4d09cb66f5b636d7d49fbd000815r1&wshc_tag=0&wsts_tag=5d35bb97&wsid_tag=70173d21&wsiphost=ipdbm


As noted before let's keep the discussion in English as this is an international project. Use free translation services if you have to, but if the discussion continues on like this I'm going to close and lock the issue.
用wireshark获得地址也没用啊,关键是写出可用的py插件
Forrest notifications@github.com 于2019年7月23日周二 上午9:30写道:
As noted before
https://github.com/streamlink/streamlink/issues/2328#issuecomment-469414882
let's keep the discussion in English as this is an international project.
Use free translation services if you have to, but if the discussion
continues on like this I'm going to close and lock the issue.—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/streamlink/streamlink/issues/2328?email_source=notifications&email_token=AB33PNAAF24IQ22JRHJEEWLQAZNK7A5CNFSM4G2FG6Z2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2RUM7A#issuecomment-514016892,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AB33PNBYEUNF3RSN5T6N27LQAZNK7ANCNFSM4G2FG6ZQ
.
ykdl has achieved live stream resolving for 2 months, you guys DO NOT know yet???
https://github.com/zhangn1985/ykdl/tree/master/ykdl/extractors/douyu
@Justsoos It would be nice to be able to resolve this without having to embed a full javascript interpreter.
@Erk but you do not, and need not to be so freaky as DouYu(huawei, mayun ... 997)'s programmers who under abnormal pressure of much more money paid, IPO, stock, option, KPI ...
Just live in DangXia, just use it now, and it will be changed soon by DY's nerds
;p
@Erk- could import Js2Py? To transform js code to py is too cumbersome.
This is way too old to keep alive, locking.
Most helpful comment
```//length = 368
var f3 = [0x5cc389d8,0x89983bc0,0xb012db12,0x7932753b,0xd6c5b89,0x686a6c3a,0xecad9860,0x95654458,0x719096a4,0x587aaac6,0x74e3f61,0xcb466b6b,0xc8c64e18,0xf71e1e9c,0x785cb639,0x9fb3d17a,0x399f3ea5,0xdf9d92e8,0x32e9eb35,0x6576219b,0xc9402c8f,0xfff8dded,0x756fa883,0x62ddffd5,0x9ff27712,0xa8e0b421,0xc245cf71,0x898ad7ae,0x440c1a3d,0x2a653c8,0x6df3ca8f,0xb74de679,0x7c8d6fa0,0x5b408cce,0xb78b28cd,0x303ac85c,0x981707f9,0x59e24b6e,0xae5a8b16,0xafda5d1,0x39136686,0xf11b886f,0xb8e7317d,0x1c656003,0x33d85f4f,0x769c3c28,0x19a77d4,0x9f0c9108,0xab7b824b,0x5e3ac610,0x7bb5c682,0x27cc0431,0x4926e9dc,0x8973eb43,0x179c2f77,0x3d8e6861,0xd1f003a,0xa938e112,0x9c44d6ae,0x22b826d,0xeb940d5c,0x75c370e5,0xfe50872d,0xe316311b,0x806cb693,0xd552d48f,0x1fb98fb2,0x10b8ea91,0x8fa0699f,0x45f14179,0x3648e3b6,0x7f45f821,0x5585d3a0,0xe539ef80,0x36202d52,0x9112a027,0xdcea463b,0xad6aac8b,0xbd5bc4f4,0xbe230f6f,0xa7805c53,0x775e1160,0x45f997eb,0xa1415ef2,0xe664546f,0x4f67484f,0x4d914e24,0xec0b1137,0xb8a1573d,0x4bd509c2,0x3baf6130,0x4d0a3540,0x92258389,0x2ae18862,0x5316e722,0xa3adecaf,0x1a333b36,0xc86404a5,0xbe63b2d0,0x2870a1e0,0xf52612fb,0xa2c824fb,0x9924e3f0,0x76748ae,0x2fa9d945,0x20023551,0xe36c0f3f,0xd9fc9d73,0xb356a4c3,0x7e674c64,0x404276ac,0x7760d764,0x37c99e03,0x824f959d,0x85511212,0xe740d8e8,0x8d1f680,0x5c14356c,0xfa448b46,0x644b3c75,0x7b98107d,0x258ce73f,0x98ad3bef,0x6ae20b5b,0x1021af03,0xf2b092dc,0xb439f17c,0x53e81464,0x8471dc9,0x965a689c,0x3615b95c,0x1fff43f0,0x469eff63,0xa9678bf0,0x1b08fa6f,0x1bd106e2,0x90254256,0x31e53e56,0xf3f3dbfb,0x82c88f92,0xf09d989e,0xeb61e887,0xf4cd2f05,0x8b0c5704,0xa6419cca,0xaf12eac8,0xbb8e609c,0x386b3aea,0x24ad0766,0x152c1ac3,0x65abc188,0x86fd7c68,0x653ed4ea,0x7864a3e,0xe622e0b3,0xa6f04397,0xc6287931,0xad2b881a,0x25f80785,0x34420262,0x6c0c432c,0x986a6a32,0xd95d8ac4,0xaec6c8b5,0x2e2a86b,0x6621c8db,0x3a5b6266,0x7085d2ae,0x2b6c9363,0xbac3035a,0x6cbd8457,0xea4ceea9,0x19e8a2a5,0xc6d11a4,0x5a515ade,0x8756dac6,0x520b5f41,0xb2814f3,0x2697890b,0x2a24d1ee,0xe5c9b47a,0x4cf0d0e,0x5e008ab,0x61bbf8e0,0x21681c16,0x17f0550c,0xa1d4bdcc,0x90bf06af,0xedb06a60,0x9f034f1,0x71b3c15f,0x87e106d9,0xa61afc0f,0xb0e8478d,0x478b939a,0x72ab2ea0,0x6f8bccc7,0x44a595b9,0x2f788bd5,0xfc9a3222,0x9f5f956c,0x31a21055,0x7b54be72,0x91f599a3,0x7f6f811f,0x91dcb611,0x80916dd4,0x9b4718cd,0x6caf74f3,0x485e0eae,0x64c4f0e1,0xc56f7668,0x33924838,0x5ec9c6ec,0xc84f57fd,0x6defbea1,0x1e9cd613,0x8b276a43,0x7cd0b0c0,0x5cd40f74,0xa20ff79a,0xd4ae260b,0x30eef7d9,0x298907f6,0x66696d98,0x3cbe6e65,0x4a14b41d,0xc6ddb8b5,0xffa97ed2,0x8f59728d,0xd825a6f8,0x5f95d778,0x3d0806c3,0x395b69a9,0x3543bf75,0x9b0169f5,0xe88af13d,0x2e5682c8,0x9aa11f9e,0xfa0a3253,0x89a2e899,0x926cf928,0xa187d19d,0x4f681a68,0x57f3a4ed,0xaa1241b7,0x75347c7b,0xbe239450,0xf07736de,0xaba78b24,0x8263ed5f,0x1121275c,0xc30df998,0x66a6eb44,0xdb703d53,0x53f93cf9,0x7575eebe,0xbbfafbd8,0x3132ec71,0xbc2af3ff,0xc3ecd327,0x7259e92a,0x262a99bf,0x486644e3,0x5a9de2a1,0xa8d3a21e,0x5e030123,0xb87d1178,0xb335a7f0,0x23569ed4,0xb91316b7,0x7a0af8e1,0x3b186e62,0x8c074317,0x75f6a91d,0x22beea17,0xd53cd8db,0xade253a,0xdc000255,0x1101797b,0x490d5e5e,0x76324bc2,0x77f8f551,0x9e112647,0xcb175aed,0x4f5fb6cd,0x46014745,0xb999dd24,0x8b658d8,0x688e8456,0x38be6404,0x1f6cfd8,0x52808fa,0xd8459ff4,0x5e6d008c,0x4a1d87c7,0x891d18f9,0x794ee16a,0x4048930c,0xba48818a,0x5cc0eec0,0xf89b8d65,0x76dc8c7f,0x2605f404,0xf1719d4a,0xacf1f398,0xc4459281,0x8781edfc,0xd62101c6,0x28d138d6,0xc4bce54b,0xf073354a,0x317094a0,0x862cbda9,0xc45661b2,0x230e1735,0xc32f50b7,0xfd252d43,0x44dd8e18,0x32a9669c,0xc3c24680,0xd6a0a593,0xab619393,0x1ad5c8cd,0x2133b73,0x9daa213e,0x36132a22,0x8f9e7b0d,0x4d066c4b,0x25d9a264,0x33fd5b73,0xe75b65c5,0x47168d1d,0xe4e8f6ea,0x50669295,0x880d87bb,0xa70d3f77,0x67319089,0xe23349f3,0x3a528b3a,0xa47f314a,0x12be7a10,0x5885d10b,0x763a2082,0x25cea653,0x51b2151f,0x69be950e,0xa6f977fe,0x36a4e45c,0xd7436e22,0x70bf8ff,0xdff77d3b,0xc01143d1,0x5e5fa18e,0xb34827c5,0x9153473d,0x6e4228fd,0x86cfec0b,0x53369a98,0x4e775d7f,0x8bb2751a,0x3e73b9f3,0xa11bc3cb,0x59c07e58,0x66c9ff6b,0xa683b2ce,0xeb85e66a,0x9d6fa21];
function get_sign(p1, p2, p3){
/*
//length = 184
var rk=[
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28,10,32,40,31,10,
27,18,27,28
];
*/
var r_key = [27, 18, 27, 28, 10, 32, 40, 31, 10];
var rk = [];
for(var i = 0; i < f3.length / 2; i++){
rk[i] = r_key[i % 9]
}
var k2=[0x47fa3eef,0x209ff543];
var lk=k2;
var v = f3.slice(0);
var k=[0x3bbe6784,0x6cd672ae,0x96496df1,0xbfe901eb];
for(var O=0; O < f3.length; O++){
v[O]^=0x405ca50f;
}
var i = 1;
var counter = 1;
while(i < v.length){
if(i % 2)
v[i] += k2[1];
else//i % 2 == 0
v[i] += k2[0];
if(counter<2){
i+=5;
counter++;
}
else if(counter == 2){
i+=8;
counter=0;
}
}
}
get_sign('241432', 'c0ed4bd228dd366ecaf6b94200041501', '1551457047')8+6,2),16)<<24);var k2=[0x37c1f5be,0x38920f10,0x1a6000,0x713e7896];for(var I=0;I<2;I++){var v0=re[I*2],v1=re[I*2+1],sum=0,i=0;var delta=0x9e3779b9;for(i=0;i<32;i++){sum+=delta;v0+=((v1<<4)+k2[0])^(v1+sum)^((v1>>>5)+k2[1]);v1+=((v0<<4)+k2[2])^(v0+sum)^((v0>>>5)+k2[3]);}re[I2]=v0;re[I2+1]=v1;}re[0]^=k2[0];re[0]-=k2[2];re[0]=(re[0]<<(k2[2]%16))|(re[0]>>>(32-(k2[2]%16)));re[1]=(re[1]<<(k2[1]%16))|(re[1]>>>(32-(k2[1]%16)));re[1]=(re[1]>>>(k2[3]%16))|(re[1]<<(32-(k2[3]%16)));re[1]=(re[1]<<(k2[3]%16))|(re[1]>>>(32-(k2[3]%16)));re[1]=(re[1]>>>(k2[3]%16))|(re[1]<<(32-(k2[3]%16)));re[2]+=k2[0];re[2]=(re[2]>>>(k2[2]%16))|(re[2]<<(32-(k2[2]%16)));re[2]-=k2[2];re[3]-=k2[1];re[3]^=k2[3];re[3]-=k2[3];re[0]+=k2[0];re[0]^=k2[2];re[0]+=k2[2];re[0]-=k2[2];re[1]=(re[1]>>>(k2[1]%16))|(re[1]<<(32-(k2[1]%16)));re[1]^=k2[3];re[1]-=k2[3];re[2]+=k2[0];re[2]^=k2[2];re[2]^=k2[2];re[3]-=k2[1];re[3]=(re[3]>>>(k2[3]%16))|(re[3]<<(32-(k2[3]%16)));re[3]-=k2[3];{var hc='0123456789abcdef'.split('');for(var i=0;i8+4))&15]+hc[(re[i]>>(j*8))&15];re[i]=s;}re=re.join('');}var rt="v=220120180919"+"&did="+xx1+"&tt="+xx2+"&sign="+re;return rt;});;;"
"(function (xx0,xx1,xx2){var cb=xx0+xx1+xx2+"220120180919";var rb=CryptoJS.MD5(cb).toString();var re=[];for(var i=0;i
for(var O=0; O < f3.length; O++){
v[O]^=0x405ca50f;
}
for(var i=0; i
strc+=String.fromCharCode(v[i]&0xff,v[i]>>>8&0xff,v[i]>>>16&0xff,v[i]>>>24&0xff);
}
```
The hard part is to get the dynamic bit operation code and get it run in python. Once get that done the remaining part is not so difficult.