让代码更简单

python抖音请求参数a_bogus加密算法分享

重要:本文最后更新于2024-07-07 21:09:59,某些文章具有时效性,若有错误或已失效,请在下方留言或联系代码狗

今年年初的时候,抖音更新了最新的签名算法,a_bogus参数的加密请求,导致以前的x_bogus加密请求经常被拦截,等了几个月,终于等到了大佬恰饱了饭,将a_bogus加密算法开源了出来,一起来学习下吧!

复制
from random import randint
from random import random
from re import compile
from time import time
from urllib.parse import urlencode, quote


class ABogus:
__filter = compile(r'%([0-9A-F]{2})')
__arguments = [0, 1, 14]
__end_string = "cus"
__version = [1, 0, 1, 5]
__env = [
49,
53,
51,
54,
124,
55,
52,
50,
124,
49,
53,
51,
54,
124,
56,
54,
52,
124,
48,
124,
48,
124,
48,
124,
48,
124,
49,
53,
51,
54,
124,
56,
54,
52,
124,
49,
53,
51,
54,
124,
56,
54,
52,
124,
49,
53,
51,
54,
124,
55,
52,
50,
124,
50,
52,
124,
50,
52,
124,
87,
105,
110,
51,
50]
__reg = [
1937774191,
1226093241,
388252375,
3666478592,
2842636476,
372324522,
3817729613,
2969243214,
]
__str = {
"s0": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
"s1": "Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=",
"s2": "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=",
"s3": "ckdp1h4ZKsUB80/Mfvw36XIgR25+WQAlEi7NLboqYTOPuzmFjJnryx9HVGDaStCe",
"s4": "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe"}

def __init__(self, ):
self.chunk = []
self.size = 0
self.reg = self.__reg[:]

@classmethod
def list_1(cls, random_num=None, a=170, b=85, c=45, ) -> list:
return cls.random_list(
random_num,
a,
b,
1,
2,
5,
c & a,
)

@classmethod
def list_2(cls, random_num=None, a=170, b=85, ) -> list:
return cls.random_list(
random_num,
a,
b,
1,
0,
0,
0,
)

@classmethod
def list_3(cls, random_num=None, a=170, b=85, ) -> list:
return cls.random_list(
random_num,
a,
b,
1,
0,
5,
0,
)

@staticmethod
def random_list(
a: float = None,
b=170,
c=85,
d=0,
e=0,
f=0,
g=0,
) -> list:
r = a or (random() * 10000)
v = [
r,
int(r) & 255,
int(r) >> 8,
]
s = v[1] & b | d
v.append(s)
s = v[1] & c | e
v.append(s)
s = v[2] & b | f
v.append(s)
s = v[2] & c | g
v.append(s)
return v[-4:]

@staticmethod
def from_char_code(*args):
return "".join(chr(code) for code in args)

@classmethod
def generate_string_1(
cls,
random_num_1=None,
random_num_2=None,
random_num_3=None,
):
return cls.from_char_code(*cls.list_1(random_num_1)) + cls.from_char_code(
*cls.list_2(random_num_2)) + cls.from_char_code(*cls.list_3(random_num_3))

def generate_string_2(
self,
url_params: str,
user_agent: str,
start_time=0,
end_time=0,
) -> str:
a = self.generate_string_2_list(
url_params,
user_agent,
start_time,
end_time,
)
e = self.end_check_num(a)
a.extend(self.__env)
a.append(e)
return self.rc4_encrypt(self.from_char_code(*a), "y")

def generate_string_2_list(
self,
url_params: str,
user_agent: str,
start_time=0,
end_time=0,
) -> list:
start_time = start_time or int(time() * 1000)
end_time = end_time or (start_time + randint(4, 8))
params_array = self.sum(self.sum(url_params))
# TODO: 需要编写一个函数来生成ua_code 2024年6月13日17:13:08
# Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36
ua_code = [76, 98, 15, 131, 97, 245, 224, 133, 122, 199, 241, 166, 79, 34, 90, 191, 128, 126, 122, 98, 66, 11, 14, 40, 49, 110, 110, 173, 67, 96, 138, 252]
return self.list_4(
(end_time >> 24) & 255,
params_array[21],
ua_code[23],
(end_time >> 16) & 255,
params_array[22],
ua_code[24],
(end_time >> 8) & 255,
(end_time >> 0) & 255,
(start_time >> 24) & 255,
(start_time >> 16) & 255,
(start_time >> 8) & 255,
(start_time >> 0) & 255,
)

@staticmethod
def reg_to_array(a):
o = [0] * 32
for i in range(8):
c = a[i]
o[4 * i + 3] = (255 & c)
c >>= 8
o[4 * i + 2] = (255 & c)
c >>= 8
o[4 * i + 1] = (255 & c)
c >>= 8
o[4 * i] = (255 & c)

return o

def compress(self, a):
f = self.generate_f(a)
i = self.reg[:]
for o in range(64):
c = self.de(i[0], 12) + i[4] + self.de(self.pe(o), o)
c = (c & 0xFFFFFFFF)
c = self.de(c, 7)
s = (c ^ self.de(i[0], 12)) & 0xFFFFFFFF

u = self.he(o, i[0], i[1], i[2])
u = (u + i[3] + s + f[o + 68]) & 0xFFFFFFFF

b = self.ve(o, i[4], i[5], i[6])
b = (b + i[7] + c + f[o]) & 0xFFFFFFFF

i[3] = i[2]
i[2] = self.de(i[1], 9)
i[1] = i[0]
i[0] = u

i[7] = i[6]
i[6] = self.de(i[5], 19)
i[5] = i[4]
i[4] = (b ^ self.de(b, 9) ^ self.de(b, 17)) & 0xFFFFFFFF

for l in range(8):
self.reg[l] = (self.reg[l] ^ i[l]) & 0xFFFFFFFF

@classmethod
def generate_f(cls, e):
r = [0] * 132

for t in range(16):
r[t] = (e[4 * t] << 24) | (e[4 * t + 1] <<
16) | (e[4 * t + 2] << 8) | e[4 * t + 3]
r[t] &= 0xFFFFFFFF

for n in range(16, 68):
a = r[n - 16] ^ r[n - 9] ^ cls.de(r[n - 3], 15)
a = a ^ cls.de(a, 15) ^ cls.de(a, 23)
r[n] = (a ^ cls.de(r[n - 13], 7) ^ r[n - 6]) & 0xFFFFFFFF

for n in range(68, 132):
r[n] = (r[n - 68] ^ r[n - 64]) & 0xFFFFFFFF

return r

@staticmethod
def pad_array(arr, length=60):
while len(arr) < length:
arr.append(0)
return arr

def fill(self, length=60):
size = 8 * self.size
self.chunk.append(128)
self.chunk = self.pad_array(self.chunk, length)
for i in range(4):
self.chunk.append((size >> 8 * (3 - i)) & 255)

@staticmethod
def list_4(
a: int,
b: int,
c: int,
d: int,
e: int,
f: int,
g: int,
h: int,
i: int,
j: int,
k: int,
m: int,
) -> list:
return [
44,
a,
0,
0,
0,
0,
24,
b,
58,
0,
c,
d,
0,
24,
97,
1,
0,
239,
e,
51,
f,
g,
0,
0,
0,
0,
h,
0,
0,
14,
i,
j,
0,
k,
m,
3,
399,
1,
399,
1,
64,
0,
0,
0]

@staticmethod
def end_check_num(a: list):
r = 0
for i in a:
r ^= i
return r

@classmethod
def decode_string(cls, url_string, ):
decoded = cls.__filter.sub(cls.replace_func, url_string)
return decoded

@staticmethod
def replace_func(match):
return chr(int(match.group(1), 16))

@staticmethod
def de(e, r):
r %= 32
return ((e << r) & 0xFFFFFFFF) | (e >> (32 - r))

@staticmethod
def pe(e):
return 2043430169 if 0 <= e < 16 else 2055708042

@staticmethod
def he(e, r, t, n):
if 0 <= e < 16:
return (r ^ t ^ n) & 0xFFFFFFFF
elif 16 <= e < 64:
return (r & t | r & n | t & n) & 0xFFFFFFFF
raise ValueError

@staticmethod
def ve(e, r, t, n):
if 0 <= e < 16:
return (r ^ t ^ n) & 0xFFFFFFFF
elif 16 <= e < 64:
return (r & t | ~r & n) & 0xFFFFFFFF
raise ValueError

@staticmethod
def convert_to_char_code(a):
d = []
for i in a:
d.append(ord(i))
return d

@staticmethod
def split_array(arr, chunk_size=64):
result = []
for i in range(0, len(arr), chunk_size):
result.append(arr[i:i + chunk_size])
return result

@staticmethod
def char_code_at(s):
return [ord(char) for char in s]

def write(self, e, ):
if isinstance(e, str):
e = self.decode_string(e + self.__end_string)
e = self.char_code_at(e)
self.size = len(e)
if len(e) <= 64:
self.chunk = e
else:
chunks = self.split_array(e, 64)
for i in chunks[:-1]:
self.compress(i)
self.chunk = chunks[-1]

def reset(self, ):
self.chunk = []
self.size = 0
self.reg = self.__reg[:]

def sum(self, e, length=60):
self.reset()
self.write(e)
self.fill(length)
self.compress(self.chunk)
a = self.reg_to_array(self.reg)
self.reset()
return a

@classmethod
def generate_result_unit(cls, n, s):
r = ""
for i, j in zip(range(18, -1, -6), (16515072, 258048, 4032, 63)):
r += cls.__str[s][(n & j) >> i]
return r

@classmethod
def generate_result_end(cls, s, e="s4"):
r = ""
b = ord(s[120]) << 16
r += cls.__str[e][(b & 16515072) >> 18]
r += cls.__str[e][(b & 258048) >> 12]
r += "=="
return r

@classmethod
def generate_result(cls, s, n, e="s4"):
r = ""
for i in range(n):
b = ((ord(s[i * 3]) << 16) | (ord(s[i * 3 + 1]))
<< 8) | ord(s[i * 3 + 2])
r += cls.generate_result_unit(b, e)
return r

@classmethod
def generate_args_code(cls):
a = []
for j in range(24, -1, -8):
a.append(cls.__arguments[0] >> j)
a.append(cls.__arguments[1] / 256)
a.append(cls.__arguments[1] % 256)
a.append(cls.__arguments[1] >> 24)
a.append(cls.__arguments[1] >> 16)
for j in range(24, -1, -8):
a.append(cls.__arguments[2] >> j)
return [int(i) & 255 for i in a]

@staticmethod
def rc4_encrypt(plaintext, key):
s = list(range(256))
j = 0

# Key Scheduling Algorithm (KSA)
for i in range(256):
j = (j + s[i] + ord(key[i % len(key)])) % 256
s[i], s[j] = s[j], s[i]

i = 0
j = 0
cipher = []

# Pseudo-Random Generation Algorithm (PRGA)
for k in range(len(plaintext)):
i = (i + 1) % 256
j = (j + s[i]) % 256
s[i], s[j] = s[j], s[i]
t = (s[i] + s[j]) % 256
cipher.append(chr(s[t] ^ ord(plaintext[k])))

return ''.join(cipher)

def get_value(self,
url_params: dict,
user_agent: str,
start_time=0,
end_time=0,
random_num_1=None,
random_num_2=None,
random_num_3=None,
) -> str:
string_1 = self.generate_string_1(
random_num_1,
random_num_2,
random_num_3,
)
string_2 = self.generate_string_2(
urlencode(url_params),
user_agent,
start_time,
end_time,
)
string = string_1 + string_2
return self.generate_result(
string, 40, "s4") + self.generate_result_end(string, "s4")


if __name__ == "__main__":
bogus = ABogus()
USERAGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"
url_str = "https://www.douyin.com/aweme/v1/web/aweme/detail/?device_platform=webapp&aid=6383&channel=channel_pc_web&pc_client_type=1&version_code=190500&version_name=19.5.0&cookie_enabled=true&browser_language=zh-CN&browser_platform=Win32&browser_name=Firefox&browser_online=true&engine_name=Gecko&os_name=Windows&os_version=10&platform=PC&screen_width=1920&screen_height=1080&browser_version=124.0&engine_version=122.0.0.0&cpu_core_num=12&device_memory=8&aweme_id=7345492945006595379"
# 将url参数转换为字典
url_params = dict([param.split("=") for param in url_str.split("?")[1].split("&")])
print(f"URL参数: {url_params}")
a_bogus = bogus.get_value(url_params, USERAGENT)
# 使用url编码a_bogus
a_bogus = quote(a_bogus, safe='')
print(a_bogus)
print(USERAGENT)

将上面的代码保存为python文件,安装必备支持库后运行查看效果。

感觉很棒!可以赞赏支持我哟~

5 打赏

评论 (0)

登录后评论
QQ咨询 邮件咨询 狗哥推荐