- sdk/qs 平台模块(安卓参数指纹匿名搜索)+ sdk/apis/qs 取流: 匿名 30s 试听,登录态走签名 track_v2 + spade key AES-CTR 解密 - /login/qs/qr 抖音扫码登录(授权后 sessionid 解锁完整曲目) - /stream/qs/:id 解密流代理,/url 返回的相对地址按请求 host 补全 - 回归测试覆盖 kw 双通道(VIP 真音频/降级链)与 qs 试听;start.bat 去掉 SOURCE_ENABLED 直启
27 lines
1.1 KiB
TypeScript
27 lines
1.1 KiB
TypeScript
// TT 加密(设备注册请求体):gzip + SHA512 校验 + AES-128-CBC,magic 头 "tc"
|
||
// 移植自 fanqie-assistant src/crypto/ttencrypt.ts(Node crypto 实现)
|
||
import { createCipheriv, createHash, randomBytes } from 'node:crypto'
|
||
import { gzipSync } from 'node:zlib'
|
||
|
||
// 固定盐(base64 常量,社区共知)
|
||
const FIXED_STRING = Buffer.from(
|
||
'TdTC5rgxYgkOUrPHpnM7pByyRiuCmrWKGWs521cXdST0m69/COjWjSanLjfBqVovHwWlGJKu8pSXMrYqOKrdWA==',
|
||
'base64',
|
||
)
|
||
|
||
const sha512 = (data: Buffer): Buffer => createHash('sha512').update(data).digest()
|
||
|
||
export const encryptTT = (data: Buffer): Buffer => {
|
||
const rand = randomBytes(32)
|
||
const hashValue = sha512(Buffer.concat([sha512(rand), FIXED_STRING]))
|
||
const key = hashValue.subarray(0, 16)
|
||
const iv = hashValue.subarray(16, 32)
|
||
const compressed = gzipSync(data)
|
||
const payload = Buffer.concat([sha512(compressed), compressed])
|
||
const cipher = createCipheriv('aes-128-cbc', key, iv)
|
||
const encrypted = Buffer.concat([cipher.update(payload), cipher.final()])
|
||
return Buffer.concat([Buffer.from([116, 99, 5, 16, 0, 0]), rand, encrypted])
|
||
}
|
||
|
||
export default { encryptTT }
|