Files
snowy-yang 8c02fb5c15 refactor(sdk): 审计 P2 卫生项清理——请求层收敛与死代码清除
- 删除旧 sdk/request.ts,全部 import 收敛到 sdk/common/request.ts(85 文件)
- 注释死代码 630+ 行、裸 console.log 吞错 6 处、未使用符号 26 处清零
- bili 状态校验去重;utils DNS 预解析失败日志改 warn 带上下文
- CODE-AUDIT.md:第四节 P2 清理记录 + 第八节线索逐条复核结论(kw/kg/tx/wy parse 骨架相似实质各异,不抽公共层)
2026-10-03 20:48:54 +08:00

54 lines
2.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 喜马拉雅 xm-sign 生成 —— 移植 Ximalaya-Downloader-Next / easy-sign 的 du_web_sdk 签名链
// 协议:device_info → JSON → URL 编码字节 → zlib(level 6) → AES-128-ECB(PKCS7, KEY) →
// POST https://hdaa.shuzilm.cn/report?v=1.2.0&e=1&c=1&r=<uuid>(octet-stream)→
// Base64 响应 → AES-ECB 解密 → JSON 取 cadd/sid → xm-sign = "{cadd}&&{sid}"
// KEY 为 du_web_sdk _getDeviceKey(0) 的硬编码密钥;每次签名都重新上报(不缓存)。
// 模板为纯 ASCII(Base64/十六进制字段),latin1 取字节与参考实现的 charCode 语义一致。
import zlib from 'node:zlib'
import crypto from 'node:crypto'
import { httpFetch } from '../common/request.ts'
import { DEVICE_INFO } from './deviceInfo.ts'
const SIGN_KEY = 'm9ZtRrz:qujT8@da'
const REPORT_URL = 'https://hdaa.shuzilm.cn/report?v=1.2.0&e=1&c=1&r='
// 与 device_info.ew1.yV2(Chrome 125 模板)保持一致
export const XM_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36'
const aesEcb = (data: Buffer, decrypt: boolean) => {
const key = Buffer.from(SIGN_KEY, 'utf8')
const cipher = decrypt
? crypto.createDecipheriv('aes-128-ecb', key, null)
: crypto.createCipheriv('aes-128-ecb', key, null)
return Buffer.concat([cipher.update(data), cipher.final()])
}
/** 生成 xm-sign(形如 "cadd&&sid");每次调用重新上报设备指纹 */
export const makeXmSign = async(): Promise<string> => {
const info = { ...DEVICE_INFO, Zf5: Date.now() }
const compressed = zlib.deflateSync(Buffer.from(JSON.stringify(info), 'latin1'), { level: 6 })
const payload = aesEcb(compressed, false)
const { statusCode, body, raw } = await httpFetch(`${REPORT_URL}${crypto.randomUUID()}`, {
method: 'post',
headers: {
'Content-Type': 'application/octet-stream',
'User-Agent': XM_UA,
Host: 'hdaa.shuzilm.cn',
},
body: payload,
timeout: 15000,
}).promise as any
const respText = raw ? raw.toString('utf8') : String(body ?? '')
if (statusCode != 200) throw new Error(`xm-sign 上报失败: HTTP ${statusCode}`)
const decrypted = aesEcb(Buffer.from(respText, 'base64'), true).toString('utf8')
const obj = JSON.parse(decrypted)
const cadd = String(obj.cadd || '')
const sid = String(obj.sid || '')
if (!cadd || !sid) throw new Error('xm-sign 上报响应缺少 cadd/sid')
return `${cadd}&&${sid}`
}
export default { makeXmSign, XM_UA }