Files
autoPlus/utils/fingerprint.py
2026-01-26 16:25:22 +08:00

176 lines
6.7 KiB
Python
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.
# 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"]