114 lines
3.5 KiB
Python
114 lines
3.5 KiB
Python
# modules/sentinel_solver.py
|
||
"""Sentinel 挑战求解器"""
|
||
|
||
import json
|
||
import uuid
|
||
from typing import Dict, Optional
|
||
|
||
from reference.js_executor import JSExecutor
|
||
from utils.fingerprint import BrowserFingerprint
|
||
from reference.config import DEBUG
|
||
|
||
|
||
class SentinelSolver:
|
||
"""协调指纹生成和 JS 执行,生成完整的 Sentinel tokens"""
|
||
|
||
def __init__(self, fingerprint: BrowserFingerprint):
|
||
self.fingerprint = fingerprint
|
||
self.js_executor = JSExecutor()
|
||
|
||
def generate_requirements_token(self) -> Dict[str, str]:
|
||
"""
|
||
生成 requirements token(初始化时需要)
|
||
|
||
Returns:
|
||
{'p': 'gAAAAAC...', 'id': 'uuid'}
|
||
"""
|
||
if DEBUG:
|
||
print("[Solver] Generating requirements token...")
|
||
|
||
# 生成随机 seed
|
||
req_seed = str(uuid.uuid4())
|
||
|
||
# 获取指纹配置
|
||
config_array = self.fingerprint.get_config_array()
|
||
|
||
# 调用 JS 求解
|
||
answer = self.js_executor.generate_requirements(req_seed, config_array)
|
||
|
||
token = {
|
||
'p': f'gAAAAAC{answer}',
|
||
'id': self.fingerprint.session_id,
|
||
}
|
||
|
||
if DEBUG:
|
||
print(f"[Solver] Requirements token: {token['p'][:30]}...")
|
||
|
||
return token
|
||
|
||
def solve_enforcement(self, enforcement_config: Dict) -> str:
|
||
"""
|
||
解决完整的 enforcement 挑战(PoW + Turnstile)
|
||
|
||
Args:
|
||
enforcement_config: 服务器返回的挑战配置
|
||
{
|
||
'proofofwork': {
|
||
'seed': '...',
|
||
'difficulty': '0003a',
|
||
'token': '...', # cached token
|
||
'turnstile': {
|
||
'dx': '...' # VM bytecode
|
||
}
|
||
}
|
||
}
|
||
|
||
Returns:
|
||
完整的 Sentinel token (JSON string)
|
||
"""
|
||
if DEBUG:
|
||
print("[Solver] Solving enforcement challenge...")
|
||
|
||
pow_data = enforcement_config.get('proofofwork', {})
|
||
|
||
# 1. 解决 PoW
|
||
seed = pow_data['seed']
|
||
difficulty = pow_data['difficulty']
|
||
|
||
config_array = self.fingerprint.get_config_array()
|
||
pow_answer = self.js_executor.solve_pow(seed, difficulty, config_array)
|
||
|
||
# 2. 执行 Turnstile(如果有)
|
||
turnstile_result = None
|
||
turnstile_data = pow_data.get('turnstile')
|
||
|
||
if turnstile_data and turnstile_data.get('dx'):
|
||
dx_bytecode = turnstile_data['dx']
|
||
xor_key = self.fingerprint.session_id # 通常用 session ID 作为密钥
|
||
|
||
turnstile_result = self.js_executor.execute_turnstile(dx_bytecode, xor_key)
|
||
|
||
# 3. 构建最终 token
|
||
sentinel_token = {
|
||
# enforcement token 前缀为 gAAAAAB(requirements 为 gAAAAAC)
|
||
'p': f'gAAAAAB{pow_answer}',
|
||
'id': self.fingerprint.session_id,
|
||
'flow': 'username_password_create',
|
||
}
|
||
|
||
# 添加可选字段
|
||
if turnstile_result:
|
||
sentinel_token['t'] = turnstile_result
|
||
|
||
if pow_data.get('token'):
|
||
sentinel_token['c'] = pow_data['token']
|
||
|
||
token_json = json.dumps(sentinel_token)
|
||
|
||
if DEBUG:
|
||
print(f"[Solver] Sentinel token generated: {token_json[:80]}...")
|
||
|
||
return token_json
|
||
|
||
|