Files
hello_js_reverse_skill/templates/python-request/utils/sign.py
T
白夜 b5cf8b121a feat(v2.4.0): JSVMP 双路径攻克体系 + jsdom 环境补丁知识库
基于实战经验重构 JSVMP 分析框架:

- SKILL.md: 新增路径选择决策树(路径 A 算法追踪 vs 路径 B 环境伪装)
- SKILL.md: 路径 B「环境伪装六步法」完整方法论(采集→对比→分级→补丁→验证→端到端)
- SKILL.md: 新增场景 10「JSVMP + jsdom 环境伪装」、解法模式 E
- SKILL.md: 标注三板斧适用边界与局限,经验法则扩充至 22 条
- references/jsdom-env-patches.md: 新增 jsdom 环境补丁知识库(Function.toString 三层防御 / plugins 完整模拟 / DOM 布局属性 / 30+ API 存根)
- cases/: 新增经验库系统(模板 + 首个 JSVMP 实战案例含 58 项环境检测差异全表)
- references/jsvmp-analysis.md: JSVMP 专项分析详细指南
- references/troubleshooting.md: 常见问题排查指南
- templates/python-request/: Python 项目模板
- 各 references 文档增强、Python 技术栈支持、MCP v1.1 适配(44→52 工具)

Made-with: Cursor
2026-04-02 18:10:05 +08:00

109 lines
2.9 KiB
Python
Raw 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.
"""
签名函数封装
根据逆向分析结论修改具体的签名逻辑
"""
import hashlib
import hmac
import base64
import json
import time
# 如需执行提取的 JS 代码
# import execjs
def md5(text: str) -> str:
"""MD5 哈希(返回 32 位小写 hex)"""
return hashlib.md5(text.encode("utf-8")).hexdigest()
def sha256(text: str) -> str:
"""SHA-256 哈希(返回 64 位小写 hex)"""
return hashlib.sha256(text.encode("utf-8")).hexdigest()
def hmac_sha256(key: str, message: str) -> str:
"""HMAC-SHA256 签名(返回 hex)"""
return hmac.new(
key.encode("utf-8"),
message.encode("utf-8"),
hashlib.sha256
).hexdigest()
def aes_encrypt(plaintext: str, key: str, iv: str) -> str:
"""AES-CBC 加密(返回 Base64)"""
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
cipher = AES.new(
key.encode("utf-8"),
AES.MODE_CBC,
iv.encode("utf-8")
)
padded = pad(plaintext.encode("utf-8"), AES.block_size)
encrypted = cipher.encrypt(padded)
return base64.b64encode(encrypted).decode("utf-8")
def aes_decrypt(ciphertext_b64: str, key: str, iv: str) -> str:
"""AES-CBC 解密"""
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
cipher = AES.new(
key.encode("utf-8"),
AES.MODE_CBC,
iv.encode("utf-8")
)
decrypted = cipher.decrypt(base64.b64decode(ciphertext_b64))
return unpad(decrypted, AES.block_size).decode("utf-8")
def generate_sign(params: dict, secret_key: str) -> str:
"""
生成请求签名(根据实际逻辑修改)
示例签名逻辑:
1. 参数按 key 字典序排序
2. 拼接为 key1=value1&key2=value2 格式
3. 末尾追加密钥
4. 对拼接字符串做 MD5
Args:
params: 请求参数字典
secret_key: 签名密钥
Returns:
签名字符串
"""
sorted_params = sorted(params.items(), key=lambda x: x[0])
param_str = "&".join(f"{k}={v}" for k, v in sorted_params)
sign_str = f"{param_str}&key={secret_key}"
# 打印签名明文(调试用,正式使用时删除)
print(f" 签名明文: {sign_str}")
result = md5(sign_str)
print(f" 签名结果: {result}")
return result
def generate_m(params: dict, encrypt_key: str, iv: str) -> str:
"""
生成加密参数 m(根据实际逻辑修改)
示例:将参数 JSON 序列化后 AES 加密
"""
plaintext = json.dumps(params, separators=(",", ":"), sort_keys=True)
return aes_encrypt(plaintext, encrypt_key, iv)
# ====== execjs 方式(当 JS 逻辑过于复杂时使用)======
#
# def generate_sign_via_js(params: dict) -> str:
# """使用 execjs 执行提取的 JS 代码生成签名"""
# with open("config/sign_logic.js", "r", encoding="utf-8") as f:
# js_code = f.read()
# ctx = execjs.compile(js_code)
# return ctx.call("generateSign", params)