chrome-fp — 与真 Chrome 逐字节同指纹的纯 Python 请求库, 用法和 requests 一样
用 Python 发 HTTP 请求, 但 TLS/HTTP2 指纹跟本机真 Chrome(153.0.8010.48)一致: JA4、HTTP/2 Akamai 指纹、请求头顺序与取值、扩展集合、GREASE、ALPS、trust_anchors、 PQ 混合密钥共享(X25519MLKEM768)全部对齐。
import chrome_fp as requests # 就当成 requests 用
r = requests.get("https://example.com/", params={"a": 1}, timeout=10)
print(r.status_code, r.headers["Content-Type"], r.elapsed)
print(r.text, r.json() if "json" in r.headers.get("content-type", "") else "")
with requests.Session() as s:
s.headers.update({"x-token": "abc"})
r = s.post("https://httpbin.org/post", json={"a": 1})
r.raise_for_status()
本轮做了什么:拿真机抓包把库对齐
本机是非管理员,Npcap/dumpcap 直接拒绝抓包
(You do not have permission to capture on device)。所以改用应用层旁路抓包:
Chrome ──CONNECT──> tools/tap_proxy.py ──> 真实服务器 / 本地 h2 服务器
│
├─ 原样录下双向字节(不改一个字节)
├─ 合成 TCP 头写成 .pcap ──> tshark / Wireshark 打开
└─ Chrome 的 SSLKEYLOGFILE ──> 解密看 HTTP/2 帧
产物在 capture/chrome153/(另有 capture/library/ 是本库走同一流程的抓包,用来对比):
| 文件 | 内容 |
|---|---|
chrome_tap.pcap |
合成 TCP 的抓包文件,Wireshark 可直接打开(304 包 / 23 条隧道) |
sslkeylog.txt |
Chrome 自己写的 TLS 会话密钥 |
hello/*.bin |
真 Chrome 发出的 ClientHello 原始字节(17 条样本) |
streams/*.bin |
每条隧道双向的原始字节流 |
h2_client.json |
解密后解出的请求头(顺序 + 取值) |
summary.txt |
按资源类型归类的头顺序汇总 |
tls_diff.txt |
与库的逐扩展对比结论(完全一致) |
report.json |
tshark 判定结果(JA4/JA3/扩展/key_share…) |
抓包自己也能复现:
python tools/run_capture.py --out capture/chrome153 --sites https://example.com/
python tools/analyze_capture.py --dir capture/chrome153 # tshark 出 JA4 等
python tools/tls13_decrypt.py capture/chrome153 # 自己解密出 h2 明文
python tools/h2_frames.py capture/chrome153 # 解 HTTP/2 帧与请求头
python tools/diff_fp.py --dir capture/chrome153 # 与库逐扩展对比
tshark 4.6 能把服务端方向的 TLS 解出来,但客户端方向一直停在
Encrypted Application Data。抓包本身没问题(record 结构完整、密钥齐全), 所以tools/tls13_decrypt.py按 RFC 8446 自己解,并与 tshark 对服务端的判定互相印证。
在 Wireshark / tshark 里直接看
capture/chrome153/chrome_tap.pcap 是标准 pcap(以太网链路层 + 完整 TCP 三次握手,
tshark 能正常重组),双击就能用 Wireshark 打开:
# 1) 让 Wireshark 用 Chrome 的 keylog 解密
# GUI: 编辑 → 首选项 → Protocols → TLS → (Pre)-Master-Secret log filename
# 选 capture/chrome153/sslkeylog.txt
# tshark 等价写法: -o tls.keylog_file:capture/chrome153/sslkeylog.txt
# 2) 看真 Chrome 的 JA4(tshark 4.6 原生支持)
tshark -r capture/chrome153/chrome_tap.pcap \
-o tls.keylog_file:capture/chrome153/sslkeylog.txt \
-Y "tls.handshake.type==1" \
-T fields -e tls.handshake.extensions_server_name -e tls.handshake.ja4
# 3) 看解密后的 HTTP/2 请求头(顺序就是 Chrome 的真实顺序)
tshark -r capture/chrome153/chrome_tap.pcap \
-o tls.keylog_file:capture/chrome153/sslkeylog.txt \
-Y "http2.header.name" -T fields -e http2.streamid -e http2.header.name -e http2.header.value
本机是非管理员,
dumpcap.exe -i <任意网卡>会直接报You do not have permission to capture on device ... Admin-only Mode, 所以抓包驱动用不了(Npcap 的 NPCAP 组也不在当前令牌里,UAC 又不方便点)。 旁路代理拿到的字节和网卡抓包看到的完全一样,只是没有 TCP 重传之类的噪声; 如果你想要网卡级抓包,用管理员权限跑dumpcap -i <网卡> -w out.pcapng即可,分析流程完全一样。
抓出来的差异(已全部修掉)
| # | 项目 | 真 Chrome 153 | 旧库 (0.2.3) | 处理 |
|---|---|---|---|---|
| 1 | trust_anchors(0xca34) ID 数量 |
28 个 | 32 个(152 的集合) | 去掉 d6790902/03/09/0e 四个 |
| 2 | HTTP/2 PRIORITY 帧 |
一个都不发 | 默认发 3/5/7/9 四帧 | send_priority_tree 默认关 |
| 3 | HEADERS 帧标志 |
不带 PRIORITY 前缀 | 带 5 字节 weight 前缀 | 默认不写 |
| 4 | Akamai 指纹第 3/4 段 | 0 / m,a,s,p |
会被 #2 改成 00:256,... |
修正;m,a,s,p 其实是伪头顺序 |
| 5 | sec-ch-ua |
"Google Chrome";v="153", "Not_A Brand";v="8", "Chromium";v="153" |
152 的品牌、顺序也不同 | 更新 |
| 6 | sec-ch-ua-platform |
"Windows" |
"Linux" |
更新 |
| 7 | user-agent |
Windows NT 10.0; Win64; x64 + Chrome/153 | X11; Linux x86_64 + Chrome/152 | 更新 |
| 8 | 请求头顺序 | 导航 / 子资源两套不同顺序 | 只有一套写死的顺序 | 按 dest/mode 选 profile |
| 9 | accept / priority / referer / origin |
随资源类型变 | 全部写死 | 按 dest 取值 |
| 10 | sec-fetch-user |
只有顶层 document 导航才有 | 导航一律带 | 修正 |
TLS 层其余部分(15 个密码套件、17 个扩展+2 GREASE、11 个签名算法、 4 个 group、ECH GREASE 结构、ALPS、compress_certificate、status_request、 EMS、session_id…)经逐字节比对与 Chrome 153 完全一致。
验证结果
python tools/verify_live.py
让本库走同一个代理访问同一个本地 h2 服务器,再和 Chrome 的抓包对比:
[2/4] TLS ClientHello 对比 密码套件/扩展集合/扩展数量/trust_anchors/groups/sigalgs/versions 全部 OK
[3/4] HTTP/2 指纹对比 Akamai = 1:65536;2:0;4:6291456;6:262144|15663105|0|m,a,s,p 一致
PRIORITY 帧数量 = 0 一致
[4/4] 请求头逐条对比 document / style / font / script / image / iframe / fetch / xhr / POST
—— 9 类请求的头顺序与取值全部逐条相同
实测结果
| 项目 | 真 Chrome 153 | 本库 |
|---|---|---|
| JA4 | t13d1517h2_8daaf6152771_<随机> |
一致(17/17 条样本) |
| HTTP/2 Akamai | 1:65536;2:0;4:6291456;6:262144|15663105|0|m,a,s,p |
一致(10/10 条连接) |
| 扩展数 | 17 真实 + 2 GREASE | 一致 |
| trust_anchors | 28 个 ID(集合固定、顺序随机) | 一致 |
| 请求头顺序/取值 | 导航与子资源各一套 | 一致(逐条比对) |
实网站点:python tools/live_sites.py → 5/5
(example.com / taobao h2+TLS1.3,baidu / qq / sohu TLS1.2 回落 + HTTP/1.1)
requests 兼容的用法
Session / Response 的属性与方法刻意对齐 requests:
import chrome_fp as requests
from chrome_fp.exceptions import HTTPError, TooManyRedirects
s = requests.Session()
s.headers.update({"x-token": "abc"}) # 大小写不敏感, 单次请求头可覆盖
s.params = {"v": "1"}
s.cookies.set("sid", "x", domain="example.com")
s.auth = ("user", "pass") # 或 basic_auth/自定义可调用对象
s.proxies = {"https": "http://127.0.0.1:7892"}
s.max_redirects = 10
r = s.request("POST", "https://example.com/api",
params={"p": 1}, json={"a": 1}, timeout=(5, 20),
headers={"x-extra": "1"}, cookies={"k": "v"},
allow_redirects=True, hooks={"response": [lambda r: None]})
r.status_code; r.reason; r.ok; r.headers["CONTENT-TYPE"]; r.text; r.json()
r.content; r.raw; r.url; r.encoding; r.apparent_encoding; r.elapsed; r.history
r.cookies; r.request; r.is_redirect; r.links; r.next
r.raise_for_status(); list(r.iter_content(4096)); list(r.iter_lines())
模块级 chrome_fp.get/post/put/patch/delete/head/options/request 与 requests 同名同签名。
异常层次在 chrome_fp.exceptions(RequestException / HTTPError / Timeout /
TooManyRedirects / MissingSchema / InvalidURL / JSONDecodeError …)。
几处刻意的 requests 语义(不是 bug):
r.encoding按 requests 规则来:Content-Type 带 charset 就用它;text/*没写 charset 时是ISO-8859-1;application/json是utf-8。想要正确的中文文本就r.encoding = r.apparent_encoding(用 charset_normalizer,和 requests 一样)。r.json()解析失败抛chrome_fp.exceptions.JSONDecodeError(同时是json.JSONDecodeError)。r.iter_lines()在decode_unicode=False时给 bytes。
指纹控制(requests 没有的额外关键字)
Session(
proxy="http://127.0.0.1:7892", # 也支持 proxies={...} 和 HTTP(S)_PROXY 环境变量
mode="cors", # navigate | cors | no-cors —— 决定 sec-fetch-*
dest="empty", # document|iframe|empty|script|style|image|font|preflight
user_agent=None, # 覆盖 UA
origin=None, referer=None, # CORS / 子资源请求的上下文
sec_fetch_site=None, # none|same-origin|same-site|cross-site
priority=None, # 覆盖 RFC 9218 priority 头
send_priority_tree=False, # 只有模拟 Chrome 152 才打开
verify=True, ca_file=None, allow_tls12=True,
timeout=30, max_redirects=30, trust_env=True,
keylog_file=None, # 写 NSS key log, Wireshark 可直接解密本库流量
)
单次请求也能覆盖:s.get(url, mode="navigate", dest="document", referer=..., origin=..., priority=...)。
sec-fetch-site 需要调用方给上下文(库不知道"发起方页面"是谁),默认:
顶层 document 导航 = none,其余 = same-origin;跨站时显式传 cross-site。
底层构造单条 ClientHello(不含网络):
from chrome_fp import build_client_hello, ja4_from_hello
ch = build_client_hello("example.com")
print(ja4_from_hello(ch.record), len(ch.record))
ch.record # 可直接写 socket 的原始字节
include_mlkem=False:不发 X25519MLKEM768grease_parts=():完全关闭 GREASEpermute_extensions=False:关闭扩展随机置换(调试用)
协议实现覆盖
TLS
| 能力 | 状态 |
|---|---|
| TLS 1.3 / 1.2(同一 ClientHello 自动分派) | ✅ |
| 密码套件:AES-GCM / ChaCha20-Poly1305 / AES-CBC-SHA | ✅ |
| RSA 密钥交换(009c/009d/002f/0035) | ✅ |
| X25519MLKEM768 混合密钥共享(纯 Python ML-KEM-768) | ✅ |
| HelloRetryRequest(换 key_share 组 / cookie) | ✅ |
| 证书链校验(交叉签名根、EKU 缺失放行、通配符) | ✅ |
| CertificateVerify 验签、压缩证书(brotli)、ALPS | ✅ |
客户端证书 mTLS(cert=,TLS 1.3 与 1.2) |
✅ |
| KeyUpdate / NewSessionTicket 容忍 | ✅ |
| SSLKEYLOGFILE 导出(Wireshark 可解密本库流量) | ✅ |
| 会话恢复(PSK / session ticket)、0-RTT、ECH 真加密 | ❌ 见下 |
cert= 的用法和 requests 一致:
s.get(url, cert="client.pem") # 证书+私钥在同一个 PEM
s.get(url, cert=("client.pem", "client.key")) # 分开两个文件
Session(cert=...) # 会话级
HTTP/2
| 能力 | 状态 |
|---|---|
| Chrome 153 帧序(preface/SETTINGS/WINDOW_UPDATE/HEADERS) | ✅ |
| TLS 记录分帧(preface+SETTINGS+WINDOW_UPDATE 合成一条 record) | ✅ |
| HPACK 编码选择与 Chromium 一致(见下) | ✅ |
| 请求体流控(连接窗口 + 流窗口,等 WINDOW_UPDATE) | ✅ |
| 尊重对端 SETTINGS_MAX_FRAME_SIZE / INITIAL_WINDOW_SIZE | ✅ |
| PUSH_PROMISE(回 RST_STREAM(CANCEL)) | ✅ |
| CONTINUATION / 1xx / trailer / GOAWAY / RST_STREAM | ✅ |
流式响应(stream=True)与流式请求体(生成器) |
✅ |
HPACK 为什么重要:头解码后一样 ≠ 编码后一样。JA3/JA4/Akamai 都不看 HPACK,
但服务器/中间盒 dump 一下 HEADERS 帧的原始载荷,就能用编码方式把客户端区分开。
hpack_chromium.py 复刻了 Chromium 的选择规则,规则是从真机抓包里统计出来的
(tools/diff_wire.py 会复核):
| 规则 | 证据(真 Chrome 153 抓包) |
|---|---|
| 静态表精确命中 → 索引表示 | :method: GET、:scheme: https |
:method / :path 命中不到精确项 → 字面量+不索引(0x04) |
OPTIONS 的 :method、所有 :path |
| 其余头 → 字面量+增量索引(0x40) | cookie / referer 实测都是 0x44(不是"从不索引") |
| Huffman 择优,平局取原始字节 | /?n=0 平局→raw;/style.css 更短→Huffman |
验证方式是把抓包里每条连接上的请求按原顺序重放再逐块比字节(HPACK 动态表是连接级 状态,不按顺序重放比出来的差异是噪声):真 Chrome 抓包 32/32、本库抓包 11/11 全部逐字节复现。
Client Hints(Accept-CH)
网站用 Accept-CH 点单后,真 Chrome 会在后续请求里带上高熵 client hints。完全不发的话,
凡是下发过 Accept-CH 的站(不少 CDN 都发)一眼就能看出不是浏览器 —— 这比 JA3 更硬。
本库按规范跟踪每个源的 Accept-CH,命中后按 Chrome 的内部固定顺序回发
(顺序与取值来自探针抓包,用 tools/run_capture.py --probe + CHROME_FP_ACCEPT_CH 可复现)。
Session(client_hints=True) # 默认开
Session(client_hints=False) # 完全不发
Session(client_hint_values={"device-memory": "4"}) # 覆盖取值
⚠️ 如实说明:探针抓包里 UA 派生那几个(
full-version/full-version-list/arch/bitness/platform-version)是空串 —— 因为抓包时为让 UA 逐字节一致加了--user-agent,Chrome 会把 UA 派生的高熵 hint 置空。正常 UA 下它们有真实值,本库按 Chrome 153 / Windows x86_64 填。这几个取值没有抓包直接验证,需要精确对齐时逐项覆盖。
HTTP/1.1
| 能力 | 状态 |
|---|---|
| 定长 / chunked 响应、gzip/deflate/br/zstd | ✅ |
| chunked 请求体(生成器/无长度文件对象) | ✅ |
真流式响应(stream=True + iter_content,增量解压) |
✅ |
| 连接复用(响应头标题大小写按 Chrome 习惯) | ✅ |
Expect: 100-continue |
❌ 未实现(极少见) |
连接层
DNS 返回多个地址(尤其 IPv6 排在前面)时会自己遍历并 IPv4 优先,每个地址限时
5 秒、整体不超过 timeout。踩过的坑:socket.create_connection 按 DNS 顺序逐个用
完整 timeout 尝试,两个黑洞 IPv6 地址就能烧光整个预算 —— 实测 example.com 要 12 秒
才连上、timeout 小一点直接失败,而同一时刻 requests 只要 0.6 秒。修好后 1.1 秒。
还能被检测出来吗(现状)
分三层看,别混为一谈:
| 层 | 现状 |
|---|---|
| TLS/HTTP2 内容指纹(JA3/JA4/Akamai/扩展集合/头顺序) | 对齐(见上面各表) |
| 线上字节细节(TLS 记录分帧、HPACK 编码) | 已对齐(tools/diff_wire.py 复核:32/32、11/11) |
| Client Hints(Accept-CH) | 机制已实现,UA 派生取值未直接抓包验证 |
| 行为 / JS / 跨层一致性 | 做不到,见下 |
具体来说,下面这些仍然是"是不是浏览器"的硬伤,不是指纹库能解决的:
- 不执行 JS。Cloudflare / Akamai / DataDome / PerimeterX 最终都靠主动 JS 挑战 + 行为判定;TLS 指纹只决定"别在门口就被拦"。
- 行为不像人。单发请求、无子资源、无缓存/条件请求、请求节奏固定、长期零会话恢复。
- 跨层矛盾:库声明 Windows 平台,但 TCP/IP 栈用的是宿主机 —— 在 Linux 上跑必然 出现"Windows 浏览器 + Linux TCP 指纹",这一条比任何指纹都硬。(Windows 上自洽)
- Cookie 语义仍未实现
Secure/SameSite/ partitioned /__Host-前缀与排序规则, 服务器可以用一个Securecookie 测出来。 - 无 HTTP 缓存,从不发
If-None-Match/If-Modified-Since。 sec-fetch-site/referer/origin依赖调用方给上下文,给错就与真实页面矛盾。
故意不实现的部分(附原因)
- TLS 1.3 会话恢复(PSK / session ticket):恢复用的 ClientHello 会多出
pre_shared_key扩展,JA4 与首次连接不同。本库的真值来自 Chrome 5 次全新 profile 的首次连接(17 条样本全是 19 扩展、无 PSK),没有抓到 Chrome 的恢复握手样本。 在没有真值的情况下实现,只会让指纹从"确定对"变成"可能错",所以宁可不做。 需要的话可以先用tools/run_capture.py抓同一 profile 的第二次导航来拿真值。 - 0-RTT / early_data:本库的 ClientHello 与真 Chrome 一样不带
early_data(0x002a), 发早期数据会直接改变指纹。 - ECH 真加密:需要 DNS HTTPS 记录里的 ECHConfigList + HPKE。Chrome 只在站点发布 ECH 时才真加密,本库一律发 ECH GREASE(与抓包一致)。
- QUIC / HTTP/3:要另写一整套 QUIC 传输(丢包恢复、拥塞控制、QPACK…), 是另一个量级的工程;Chrome 走 TCP 时就是本库复刻的这套指纹。
Expect: 100-continue:极少见,收益低。
测试
python -m unittest discover -s tests -v # 86 个用例
python tools/verify_live.py # 端到端: 本库 vs 真 Chrome 抓包
python tools/diff_wire.py # 线级: TLS 记录分帧 + HPACK 编码字节
python tools/live_sites.py # 实网站点冒烟
| 测试文件 | 覆盖 |
|---|---|
test_chrome153_fingerprint.py |
把 ClientHello / 请求头钉死在真机抓包上(含 key_share 私钥配对回归) |
test_hpack_chromium.py |
HPACK 编码逐字节复现真 Chrome(含动态表连续状态) |
test_client_hints.py |
Accept-CH 跟踪、高熵 hint 顺序/取值、cookie 位置 |
test_requests_api.py |
requests 语法、cookie jar、重定向、多地址连接 |
test_tls_features.py |
HRR、TLS1.2 CBC、mTLS(各自带本地 TLS 服务器) |
test_http2_features.py |
请求体流控、MAX_FRAME_SIZE、PUSH_PROMISE(h2 库的流控检查当裁判) |
test_streaming.py |
chunked 上传、stream=True 真流式、增量解压 |
构建与发布
python -m pip install build wheel twine
python -m build # 产出 dist/chrome_fp-0.4.0-py3-none-any.whl 和 .tar.gz
python tools/verify_build.py # 校验产物(清单/METADATA/隔离安装冒烟/sdist 自举)
python -m twine check dist/* # README 渲染与元数据检查
python -m twine upload dist/* # -u __token__ -p pypi-xxxx (建议用 TWINE_PASSWORD 环境变量)
python tools/verify_pypi.py # 拉回 PyPI 比 sha256, 确认传上去的和本地逐字节一致
- 已发布:chrome-fp 0.5.0(https://pypi.org/project/chrome-fp/0.5.0/) —— Chromium 一致的 HPACK 编码 / TLS 记录分帧 / Accept-CH 高熵 hints
- 历史版本:0.4.0(HRR / TLS1.2 CBC / 客户端证书 / HTTP2 请求体流控 / 真流式)、 0.3.0(Chrome 153 指纹对齐)、0.2.x(Chrome 152)
pip install chrome-fp # 或者 pip install "chrome-fp[encoding]"
verify_build.py 会把 wheel 解到临时目录,用那个副本跑一遍真实功能
(拼 ClientHello、算 JA4、requests 风格 prepare_request),确保校验的不是源码树;
再确认 sdist 解包后能自己重新构建出 wheel。
- wheel 里只有
chrome_fp包(16 个模块)+ LICENSE + METADATA - sdist 额外带
tests/、tools/,但不含体积大的capture/抓包数据 chrome_fp.zip是同样内容的便携 zip(源码 + README + pyproject + LICENSE)
目录结构
chrome_fp/
spec.py Chrome 153 指纹常量 + 每种资源类型的头顺序 profile(全部标注出处)
hello.py 按 BoringSSL ssl_add_clienthello_tlsext 规则拼 ClientHello
fingerprint.py 解析 + JA3/JA4 计算
tls13.py 纯 Python TLS 1.3 客户端(record 层/密钥调度/CV 校验/证书链校验/KeyUpdate/keylog)
tls12.py TLS 1.2 回落(ECDHE/RSA + GCM/ChaCha20/**CBC**, EMS, 客户端证书)
clientcert.py 客户端证书加载 + 签名算法选择 + TLS1.2/1.3 证书消息构造
client.py 发同一个 ClientHello, 按 ServerHello 自动分派 1.3 / 1.2
mlkem.py ML-KEM-768 (FIPS 203) 纯 Python
http2.py HTTP/2 客户端(帧序/SETTINGS/头顺序/请求体流控/推送/流式)
hpack_chromium.py HPACK 编码选择与 Chromium 一致(编码字节可逐字节复现)
_huffman_table.py RFC 7541 附录 B 的 Huffman 表(生成物, 不依赖 hpack 内部实现)
http1.py HTTP/1.1 客户端(Title-Case 头名 / chunked / 流式)
session.py requests 风格的 Session / Response / PreparedRequest
api.py 模块级 get/post/...(与 requests 同名同签名)
structures.py CaseInsensitiveDict / RequestsCookieJar
exceptions.py 与 requests.exceptions 对应的异常层次
tools/ 抓包(代理/本地h2服务器/解密)、分析(tshark/HTTP2)、构建与发布校验
tests/ 单元 + 与真机抓包的回归测试(71 个用例)
capture/ 本轮真 Chrome 153 的抓包与判定结果
已知边界
www.google.com/www.googleapis.com:握手能完成(JA4 一致),但 GFE 随后用unexpected_message断链。本机到 Google 的 IP 被黑洞/污染(tcp都连不上), 暂时无法进一步定位。其余实测站点正常。- JA3 每次连接都不同,这是真 Chrome 的行为(扩展顺序随机置换),不是 bug; 稳定的标识是 JA4。
- 扩展顺序、GREASE 取值、ECH GREASE 长度、trust_anchors 顺序都是每次连接随机的 (与 Chrome 相同分布)。
- 会话恢复 / 0-RTT / ECH 真加密 / QUIC-HTTP3 故意未实现,原因见上面「故意不实现的部分」。
- 连接策略是 IPv4 优先(Chrome 用 happy eyeballs 并发尝试)。对黑白洞 IPv6 的环境 这是必要的取舍,但严格来说与 Chrome 的连接时序不同 —— 这不影响 TLS/HTTP2 指纹。
真值来源
- 本机真 Chrome 153.0.8010.48(Windows x64)的抓包:22 条 ClientHello +
10 条 HTTP/2 连接(
capture/chrome153/),JA4 由 tshark 4.6.4 判定 - 本地 Chromium/BoringSSL 源码:
- 扩展表顺序与置换:
boringssl/src/ssl/extensions.cc:4067-4295, 4306-4328 - GREASE 首尾与 padding 规则:
extensions.cc:4489-4560 - ECH GREASE 长度:
boringssl/src/ssl/encrypted_client_hello.cc:732-784 - trust_anchors(0xca34):
include/openssl/tls1.h:141+extensions.cc:2948-2965 - 混合密钥共享拼接顺序:
boringssl/src/ssl/ssl_key_share.cc:308-346 - TLS 客户端配置:
net/socket/ssl_client_socket_impl.cc
- 扩展表顺序与置换:
Metadata
Release files for chrome-fp 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| chrome_fp-0.5.0.tar.gz | 154.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| chrome_fp-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 247.0 kB
Release files / chrome_fp-0.5.0.tar.gz
| Download URL | chrome_fp-0.5.0.tar.gz |
|---|---|
| Size | 154.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b1c9043b1db84d2639eecde3eb9bcc313c8371327b38a203ad68aa89d04b182b
|
|
BLAKE2b-256 checksum How to use checksums |
9aa90b96ec4ce4af21f84d7307b38a243d295196f985e095cdc1c804ebb5943a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / chrome_fp-0.5.0-py3-none-any.whl
| Download URL | chrome_fp-0.5.0-py3-none-any.whl |
|---|---|
| Size | 93.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
091e113bf63cc0fdae7763de67bf50212297fd9e9f2dcfb4b2942b775713a6bb
|
|
BLAKE2b-256 checksum How to use checksums |
fc55e652d5ff3033644eb8da7289852e20ee534aabe37190079b6b553577bdab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|