"""虎牙 udb 登录证书 (biz_token) 铸造与解析工具。 证书格式:base64( [0x0c][key_idx][AES-128-ECB(key16, zeropad(P1))] ) """ from __future__ import annotations import os import struct from .udb_aes import udb_decrypt, udb_encrypt KEY_TABLE_RAW = [ "4VYcPdvKKqjBHZtCmbroRXHk", "xXEDWqiKLGwEZ6HubEiswCqK", "3FMHubdKosFrhmXNLHTNHZwe", ] DEFAULT_KEY16 = KEY_TABLE_RAW[0][:16].encode() def build_p1( app_id: bytes, fingerprint: bytes, cred: bytes, rnd: bytes | None = None, ) -> bytes: """按样本结构组装 P1 明文。 - app_id: b'5008' 等 4 字节 - fingerprint: 40 字节 ASCII hex - cred: 114 字节 hyCred - rnd: 20 字节 nonce,缺省用 os.urandom(20) """ assert len(fingerprint) == 40, f"指纹应为40B, 实际为 {len(fingerprint)}" assert len(cred) == 114, f"cred应为114B, 实际为 {len(cred)}" r = os.urandom(20) if rnd is None else rnd p1 = b"\x01\x04\x00" + app_id p1 += struct.pack(" dict: """解析 P1 结构。""" o = 0 def tk(n: int) -> bytes: nonlocal o b = data[o : o + n] o += n return b out = { "head": tk(3).hex(), "app_id": tk(4), } n = struct.unpack(" bytes: """P1 -> 二进制证书 [type][key_idx][192B AES 密文]。""" ct = udb_encrypt(key16, p1) assert len(ct) == 192, len(ct) return bytes([type_byte, key_idx]) + ct def parse_cert(blob: bytes) -> tuple[int, int, bytes]: """[0x0c][idx][192B] -> (type, idx, ct)。""" assert blob[0] == 0x0C and len(blob) >= 194, "非证书结构" return blob[0], blob[1], blob[2:194] def decrypt_cert(blob: bytes, key16: bytes = DEFAULT_KEY16) -> bytes: """解密二进制证书为 P1 明文。""" _, _, ct = parse_cert(blob) return udb_decrypt(key16, ct)