kexinoh/llm_sign

GitHub: kexinoh/llm_sign

llm_sign是一个为LLM交互提供端到端密码学签验的协议与库,让客户端能验证收到的响应确实来自声称的模型提供商且未被中间人篡改。

Stars: 1 | Forks: 0

# llm_sign [![PyPI 版本](https://img.shields.io/pypi/v/llm-sign.svg)](https://pypi.org/project/llm-sign/) [![Python 版本](https://img.shields.io/pypi/pyversions/llm-sign.svg)](https://pypi.org/project/llm-sign/) [![许可证](https://img.shields.io/pypi/l/llm-sign.svg)](https://github.com/kexinoh/llm_sign/blob/master/LICENSE) ## 实验 / 测试版本状态 本代码库和协议目前处于 **测试阶段**。它们可能随时引入破坏性更新,因此 **不建议在生产环境中使用**。 ## 我们在做什么(以及为什么) **一句话概括:`llm_sign` 的存在是为了阻止位于你与 LLM 提供商之间的“中继 / 网关 / API 聚合器”静默替换模型、篡改响应内容,或伪造提供商从未实际生成的响应。** 如今,几乎所有真实的 LLM 部署看起来都是这样的: ``` your client ──HTTPS──▶ relay / gateway / aggregator ──HTTPS──▶ the real model provider (e.g. vLLM) ``` 你的 HTTPS 会话只能证明“我确实连接到了中继”。它**无法**证明以下任何一点: - 中继是否悄悄将你请求的 `gpt-x-large` 降级为更便宜的小型模型并返回了该结果; - 中继是否在响应返回途中编辑、删除或重写了部分响应体; - 你收到的响应是否真的由提供商生成,还是完全由中继捏造; - 你发出的请求是否原封不动地到达了提供商。 **`llm_sign` 正是为了填补这一空白。** 其机制如下: 1. 真正的提供商使用**其自己的 TLS 私钥**对每个 `(请求, 响应)` 交互进行端到端签名,并在响应 JSON 的 `response["llm_sign"]` 字段中,将**其 TLS 证书链**与签名一起发送。 2. 客户端使用**与浏览器针对 HTTPS 服务器相同的标准化 X.509 路径验证**来验证该链——即针对系统 TLS 信任库进行验证,并匹配 SAN 名称——然后根据已验证的叶证书公钥来验证交互记录签名。 3. 由于中继**不**持有提供商的 TLS 私钥,因此中继无法: - 篡改内容(对可见响应体——`choices`、`model` 等——的任何编辑都会被检测到:高层级的 `verify_openai_response*` API 会将用户可见的主体固定到链的终结 `provider_output` 块上,因此保留签名产物而仅重写可见字段的中继会因为 `payload digest mismatch` 被拒绝); - 替换模型(模型名称和输出都在已签名的交互记录中); - 提供省略响应的链(最后一个块为 `provider_received_input` 的链会被拒绝——每一个签名的输入都必须由一个签名的 `provider_output` 来关闭); - 伪造“提供商响应”(无法生成有效签名); - 替换证书(签名的 `key_id` 是签名者公钥的 SPKI-SHA256,并且会与已验证叶证书的 SPKI 进行交叉核对)。 请注意,我们故意**没有**发明新的 PKI、运行自己的 CA 或定义自定义 OID / EKU。信任根仅仅是系统的 Web PKI 信任库:提供商上的任何普通 HTTPS 证书(Let's Encrypt、企业 CA 等)在默认客户端配置下即可直接使用。 完整的威胁模型和线格式规范位于 [`spec/provider-certificate-binding.md`](spec/provider-certificate-binding.md) 中。 ### 这种威胁并非假设 最近的研究在实际环境中精确测量了 `llm_sign` 旨在防御的中继层不当行为: - **"Real Money, Fake Models: Deceptive Model Claims in Shadow APIs"** ([arXiv:2603.01919](https://arxiv.org/abs/2603.01919) · [alphaXiv](https://www.alphaxiv.org/overview/2603.01919)) — 记录了第三方“影子 API”转售商在收取高级模型费用的同时,静默将流量路由到更便宜或不同模型的行为。这就是上述在真实商业端点上观察到的**模型替换**攻击。 - **"Your Agent Is Mine: Measuring Malicious Intermediary Attacks on the LLM Supply Chain"** ([arXiv:2604.08407](https://arxiv.org/abs/2604.08407) · [alphaXiv](https://www.alphaxiv.org/abs/2604.08407)) — 测量了 LLM 供应链中在客户端和真实提供商之间修改、重定向或劫持 Agent 流量的恶意中介。这属于**中继篡改 / 响应伪造**攻击类别。 这两篇论文都证实,单纯的 `客户端 ──HTTPS──▶ 中继 ──HTTPS──▶ 提供商` 拓扑结构**无法**为客户端提供关于究竟是哪个模型实际作答或答案在传输途中是否被篡改的任何密码学证据。`llm_sign` 提供的正是这些缺失的证据。 ## 安装 ``` pip install llm-sign ``` ## 快速入门(客户端):验证已签名的响应 提供商在响应中发送其证书。默认验证器会针对系统 TLS 信任库对其进行认证: ``` import json import llm_sign response = json.loads(http_body) # raw response from the (possibly relayed) endpoint result = llm_sign.client.verify_openai_response(response) if result.valid: print("authentic:", response["choices"][0]["message"]["content"]) else: print("rejected :", result.errors) ``` **这实际检查了什么。** 客户端在嵌入的链上运行标准的 TLS / X.509 服务器证书验证算法(系统信任库 + 针对预期主机的 SAN 匹配),将已签名的 `key_id` 与已验证叶证书的 SPKI 进行交叉核对,然后验证交互记录签名。对请求、响应或交互记录的任何篡改都会使 `valid` 变为 `False`;将嵌入的链替换为非信任库根植的链会导致链验证失败;将叶证书替换为拥有不同密钥的证书会导致 `key_id` 匹配失败。 ### 私有 / 自签名提供商 如果提供商不使用 Web PKI 证书,请传递显式的信任锚集合或选择信任首次使用(trust-on-first-use): ``` # Private CA from llm_sign.client import verify_openai_response result = verify_openai_response(response, trust_anchors=my_root_certs) # Self-signed / local dev (trust embedded cert as-is) result = verify_openai_response(response, verify_tls=False) ``` ### 同样支持较旧的提供商 并非每个端点都会对响应进行签名。对于希望同时接受已签名和未签名提供商的客户端,请使用非抛出异常的变体: ``` report = llm_sign.client.verify_openai_response_signature(response) report.has_signature # True / False report.host_name # provider host name, if signed report.valid # True / False / None (None = no signature to check) ``` ### 锁定已知提供商密钥 如果你通过带外方式获取了提供商的公钥,并希望完全跳过证书处理: ``` from llm_sign.client import verify_openai_response_with_public_key result = verify_openai_response_with_public_key(response, public_key=pinned) ``` ## 快速入门(提供商):对响应进行签名 如果你运行自己的 OpenAI 兼容 API,并且已经拥有主机的 TLS 证书,只需几行代码即可完成签名: ``` import llm_sign credential = llm_sign.server.TLSCertificateCredential.from_files( ssl_certfile="/etc/letsencrypt/live/api.example.com/fullchain.pem", ssl_keyfile="/etc/letsencrypt/live/api.example.com/privkey.pem", ) signer = credential.signer() artifact = llm_sign.server.sign_openai_chat_turn( request=request_dict, # your OpenAI-compatible request body response=response_dict, # your OpenAI-compatible response body signer=signer, ) # 将 artifact 以及 provider certificate chain 附加到 HTTP 响应: llm_sign.server.attach_signed_artifact_to_openai_response( response_dict, artifact=artifact, credential=credential, ) ``` 签发者(签名中声称的提供商标识)是从你证书的 SAN/CN 派生的,因此它会自动与你的 TLS 服务器名称匹配。RSA 和 P-256 ECDSA 证书在系统 Web PKI 下可以直接通过验证;Ed25519 证书受签名套件支持,但目前需要私有信任锚集合,因为公共 Web PKI 尚未接受它们。 ## 在 vLLM 中使用 llm_sign 自 [kexinoh/vllm](https://github.com/kexinoh/vllm) 集成起,vLLM 已为 `llm_sign` 提供一流的支持。只需设置两个指向你 TLS 材料的环境变量即可启用它: ``` pip install vllm llm-sign export VLLM_LLM_SIGN_ENABLED=1 export VLLM_LLM_SIGN_CERTFILE=/path/to/cert.pem export VLLM_LLM_SIGN_KEYFILE=/path/to/key.pem vllm serve meta-llama/Meta-Llama-3-8B-Instruct ``` 现在,每个非流式 `/v1/chat/completions` 响应都会包含一个 `llm_sign` 字段。当环境变量未设置时,响应与上游 vLLM 的字节完全一致:没有 schema 更改,没有新增键,也不会导致客户端中断。 ## 命令行验证器 对于离线 / 审计用途,CLI 接受一个固定的公钥(或一个使用其公钥的 PEM 证书)。它不运行 TLS 链检查——只需传入你已信任的密钥: ``` llm-sign-verify artifact.json \ --issuer api.example.com \ --public-key provider-cert.pem ``` ## 协议与版本控制 每个签名产物都包含一个微小的 `protocol` 块: ``` { "protocol": {"version": 1, "min_reader_version": 1}, ... } ``` 读取器会拒绝 `min_reader_version` 高于其理解版本的签名产物,并显示清晰的“请升级 llm_sign”提示。协议整数明确**解耦**于 Python 包版本:错误修复、重构和新增辅助功能永远不会改变它;只有线格式发生变化时才会更新。 ## 了解更多 - [spec/normalization.md](spec/normalization.md) — 规范 JSON 与摘要构造 - [spec/provider-certificate-binding.md](spec/provider-certificate-binding.md) — 证书认证与密钥绑定 - [docs/artifact.md](docs/artifact.md) — 已签名的签名产物封装 - [example/](example/) — 可运行脚本,包括离线验证与篡改检测演示 ## 许可证 Apache-2.0。详见 [LICENSE](LICENSE)。
标签:API网关, API聚合器, CVE, DLL 劫持, JSON Web签名, OpenAI兼容, Petitpotam, Python, TLS证书, X.509, Zenmap, 中间人攻击防护, 可验证计算, 响应防伪, 大语言模型, 密码学, 底层编程, 手动系统调用, 数字签名, 数据完整性, 无后门, 端到端验证, 网络安全, 逆向工具, 防篡改, 隐私保护, 零信任网络