# modules/fingerprint.py """浏览器指纹生成器""" import uuid import random import time from datetime import datetime from typing import Dict, List, Any from config import load_config class BrowserFingerprint: """生成符合 SDK 期望的浏览器指纹""" def __init__(self, session_id: str = None): self.session_id = session_id or str(uuid.uuid4()) # 新增: 使用确定性方法从 session_id 派生 Stripe 指纹 import hashlib seed = hashlib.sha256(self.session_id.encode()).hexdigest() # seed 是64个hex字符,我们需要确保切片正确 # 从 seed 生成一致的 guid/muid/sid # UUID需要32个hex字符(去掉连字符),额外部分直接拼接 self.stripe_guid = seed[:8] + '-' + seed[8:12] + '-' + seed[12:16] + '-' + seed[16:20] + '-' + seed[20:32] + seed[32:40] self.stripe_muid = seed[:8] + '-' + seed[8:12] + '-' + seed[12:16] + '-' + seed[16:20] + '-' + seed[20:32] + seed[40:46] self.stripe_sid = seed[:8] + '-' + seed[8:12] + '-' + seed[12:16] + '-' + seed[16:20] + '-' + seed[20:32] + seed[46:52] # 从配置加载指纹参数 config = load_config() fingerprint_cfg = config.fingerprint_config self.user_agent = fingerprint_cfg['user_agent'] self.screen_width = fingerprint_cfg['screen_width'] self.screen_height = fingerprint_cfg['screen_height'] self.languages = fingerprint_cfg['languages'] self.hardware_concurrency = fingerprint_cfg['hardware_concurrency'] def get_config_array(self) -> List[Any]: """ 生成 SDK getConfig() 函数返回的 18 元素数组 对应 SDK 源码: [0]: screen.width + screen.height [1]: new Date().toString() [2]: performance.memory.jsHeapSizeLimit (可选) [3]: nonce (PoW 填充) [4]: navigator.userAgent [5]: 随机 script.src [6]: build ID [7]: navigator.language [8]: navigator.languages.join(',') [9]: 运行时间 (PoW 填充) [10]: 随机 navigator 属性 [11]: 随机 document key [12]: 随机 window key [13]: performance.now() [14]: session UUID [15]: URL search params [16]: navigator.hardwareConcurrency [17]: performance.timeOrigin """ # 模拟的 script sources fake_scripts = [ "https://sentinel.openai.com/sentinel/97790f37/sdk.js", "https://chatgpt.com/static/js/main.abc123.js", "https://cdn.oaistatic.com/_next/static/chunks/main.js", ] # 模拟的 navigator 属性名 navigator_props = [ 'hardwareConcurrency', 'language', 'languages', 'platform', 'userAgent', 'vendor' ] # 模拟的 document keys document_keys = ['body', 'head', 'documentElement', 'scripts'] # 模拟的 window keys window_keys = ['performance', 'navigator', 'document', 'location'] current_time = time.time() * 1000 return [ self.screen_width + self.screen_height, # [0] str(datetime.now()), # [1] None, # [2] memory None, # [3] nonce (placeholder) self.user_agent, # [4] random.choice(fake_scripts), # [5] "97790f37", # [6] build ID self.languages[0], # [7] ",".join(self.languages), # [8] None, # [9] runtime (placeholder) f"{random.choice(navigator_props)}−{random.randint(1, 16)}", # [10] random.choice(document_keys), # [11] random.choice(window_keys), # [12] current_time, # [13] self.session_id, # [14] "", # [15] URL params self.hardware_concurrency, # [16] current_time - random.uniform(100, 1000), # [17] timeOrigin ] def get_cookies(self) -> Dict[str, str]: """生成初始 cookies""" return { 'oai-did': self.session_id, } def get_stripe_fingerprint(self) -> Dict[str, str]: """获取 Stripe 支付指纹(与 session_id 一致派生)""" return { 'guid': self.stripe_guid, 'muid': self.stripe_muid, 'sid': self.stripe_sid, } def get_headers(self, with_sentinel: str = None, host: str = 'auth.openai.com') -> Dict[str, str]: """生成 HTTP headers(支持多域名)""" # 基础 headers headers = { 'User-Agent': self.user_agent, 'Accept': 'application/json', 'Accept-Language': f"{self.languages[0]},{self.languages[1]};q=0.5", # Note: urllib3/requests only auto-decompress brotli/zstd when optional # deps are installed; avoid advertising unsupported encodings. 'Accept-Encoding': 'gzip, deflate', 'Connection': 'keep-alive', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'Priority': 'u=1, i', 'Pragma': 'no-cache', 'Cache-Control': 'no-cache', } # 根据域名设置特定 headers if 'chatgpt.com' in host: headers.update({ 'Origin': 'https://chatgpt.com', 'Referer': 'https://chatgpt.com/', }) else: headers.update({ 'Origin': 'https://auth.openai.com', 'Referer': 'https://auth.openai.com/create-account/password', 'Content-Type': 'application/json', }) # Sentinel token if with_sentinel: headers['openai-sentinel-token'] = with_sentinel # Datadog RUM tracing trace_id = random.randint(10**18, 10**19 - 1) parent_id = random.randint(10**18, 10**19 - 1) headers.update({ 'traceparent': f'00-0000000000000000{trace_id:016x}-{parent_id:016x}-01', 'tracestate': 'dd=s:1;o:rum', 'x-datadog-origin': 'rum', 'x-datadog-parent-id': str(parent_id), 'x-datadog-sampling-priority': '1', 'x-datadog-trace-id': str(trace_id), }) return headers # 导出 __all__ = ["BrowserFingerprint"]