pulkit6732/aetherproof

GitHub: pulkit6732/aetherproof

为 AI 模型输出生成防篡改的离线可验证加密回执,满足 EU AI Act 等法规的记录保存与审计需求。

Stars: 4 | Forks: 1

Signet

# AetherProof **开源回执引擎。Signet 的原型。** 生成加密回执,证明 AI 输出是真实且未经修改的 —— 无需服务器,无需依赖项,可永久离线验证。 ``` pip install aetherproof ``` 不带任何参数运行 `aetherproof` 即可进入交互式菜单: ``` .+######+. AETHERPROOF ## ## v0.2.2 # /\ # Cryptographic receipt engine # / \ # Prototype of Signet · R0/L2 # / /\ \ # # / / \ \ # github.com/pulkit6732/aetherproof # /______\ \ # Verify(receipt, pk, log) = TRUE # \______/ # ## ## '######' ──────────────────────────────────────────────── Sign · Verify · Inspect · Log · Keygen ``` ## 它的功能 每次 AI 模型生成输出时,AetherProof 都会颁发一份防篡改的签名回执: ``` Receipt ID : ap_8694dae2 Model Root : abcdef0123456789... (SHA-256 Merkle of model weights) Model Root Type : artifact_hash (bound to the weights) | name_only (claim only) Output Hash : fedcba9876543210... (SHA-256 of the output) Timestamp : 2026-06-11T15:30:00Z Signature : ✓ Ed25519 VALID ``` `Model Root Type` 字段如实说明了根证明的内容: `artifact_hash`(你签名了一个真实的 weights 文件)、`api_attested`(云 API 返回了模型 ID),或者 `name_only`(你输入了一个名称)。回执绝不会 把名称伪装成 weights —— 请参阅下方的[本地与云端对比](#local-models-vs-cloud-models)。 **改变一个 bit → 签名瞬间失效。** ## 快速开始 ### 简易模式(适合所有人) ``` aetherproof ``` 分步向导: 1. 你使用了什么模型? 2. 粘贴输出内容 3. 回执被签名并保存 ### 专家模式(适合开发者) ``` # 生成 receipt aetherproof sign model.onnx output.txt # 验证它(离线,永久) aetherproof verify receipt.json # 检查所有字段 aetherproof inspect receipt.json # 测试篡改检测 aetherproof tamper receipt.json ``` ## 本地模型与云端模型 这是 AetherProof 中最重要的区别。**能够证明什么取决于你是否能看到 weights。** | | 本地/自托管 (Llama, custom, on-prem) | 云 API (GPT-4o, Claude, Grok, DeepSeek, Gemini…) | |---|---|---| | 谁持有 weights | **你** | 提供商 | | 你能对 weights 进行哈希处理吗? | **可以** | **绝对不能** | | `model_root_type` | `artifact_hash` | `api_attested` | | 证明运行了确切的模型? | **是的** | **否**(只有提供商能对此证明) | | 证明输入 + 输出未被篡改? | 是的 | **是的** | | 证明 *API 声称的模型* + 时间? | 是的 | **是的** | ### 为什么云端回执无法证明 weights —— 以及为什么这是诚实的 `model_weight_root` 需要读取 weights。对于 GPT-4o 或 Grok,**weights 存在于提供商的服务器上 —— 你永远看不到它们,因此你无法对它们进行哈希处理。** 任何客户端工具都做不到。任何声称可以“在加密意义上证明云模型运行过”的人都在夸大其词,而且精明的审计员会拒绝接受。 云端回执 *确实* 能证明的,是 **你负有责任** 的部分:你的系统发送的确切输入、它所依据的确切输出、API *声称* 的模型、时间,以及所有这些都没有被篡改或倒签日期。这是你的记录保存义务(SEC 17a-4, FRE 902(14))。提供商拥有其基础设施证明;AetherProof 负责保障你记录的准确性。 ### 模型名称是如何捕获的(你不需要手动输入) 对于 `api_attested`,模型身份来自于 **API 响应**,而不是猜测。所有主流 API 都会返回解析后的 ID: ``` # OpenAI / DeepSeek / xAI (Grok) — OpenAI-compatible resp = client.chat.completions.create(model="gpt-4o", messages=[...]) resp.model # "gpt-4o-2024-08-06" ← the RESOLVED id (dated snapshot) resp.system_fingerprint # "fp_a7d06e42bc" ← backend config snapshot resp.id, resp.created # call id + provider timestamp # Anthropic (Claude) resp = client.messages.create(model="claude-opus-4-8", ...) resp.model # "claude-opus-4-8" ``` 你请求的是 `"gpt-4o"`;API 回答 `"gpt-4o-2024-08-06"` —— 为你提供服务的确切快照。你绑定了那个返回的字符串 + `system_fingerprint`,因此用户无法伪造(它是在你正在进行哈希处理的响应内部返回的)。 ### 为云端调用签名 ``` from aetherproof.core.receipt import Receipt from aetherproof.core.keystore import load_or_create_signer from aetherproof.core.log import ReceiptLog resp = client.chat.completions.create(model="gpt-4o", messages=[...]) r = Receipt.for_api_call( provider="openai", model_id=resp.model, # read FROM the response prompt=user_prompt, output_text=resp.choices[0].message.content, response_metadata={ "system_fingerprint": resp.system_fingerprint, "response_id": resp.id, "created": resp.created, }, ) # r.model_root_type == "api_attested" signer = load_or_create_signer() r.signature = signer.sign(r.signing_bytes()) ReceiptLog().append(r) ``` 这适用于 **任何** OpenAI 兼容或 Anthropic 风格的提供商 —— OpenAI、 Azure OpenAI、DeepSeek、xAI/Grok、Mistral、Together、Groq 等(已跨越 17 个 模型族在 `tests/security/test_cloud_models_matrix.py` 中测试)。 ### “但如果他们没有提供商证明怎么办?他们会被拒绝吗?” 不会 —— 诚实的答案 *能通过* 安全审查。当被问及“证明 Grok 的 weights 运行了”时,答案是: 在真正的争议中(错误的拒绝、糟糕的摘要),争论焦点几乎从来不是 “是 GPT-4o 还是 GPT-4-turbo” —— 而是 **“AI 真的输出了这个内容,还是记录事后被编辑了?”** AetherProof 能完整回答这个问题,适用于任何云 模型,且完全不需要提供商的配合。只有当提供商对其基础设施进行签名时(AWS Bedrock + Nitro,未来),模型身份的缺口才会升级为真正的硬件根 —— 届时 **Signet** 将导入该签名,层级将提升为 `api_attested → hardware-rooted`,且回执格式无需任何更改。 ## 不变量(使之成为现实的原理) ``` Verify(receipt, public_key, log) = TRUE using ONLY those three inputs, forever, with zero dependency on AetherProof servers, any vendor SDK, or any hardware driver. ``` 这不是一句口号。它是内置的。离线验证仅使用: 1. 回执文件 2. 公钥(PEM 文件) 3.(可选)透明度日志条目 没有网络。没有 API 调用。没有特殊硬件。在 2026、2035、2050 年都能正常工作。 ## 离线验证实际是如何工作的 你可以在 **没有互联网且完全不依赖 AetherProof 代码的情况下** 证明回执是真实的 —— 数学原理是公开的。这里是具体的过程。 ### 你需要什么(三个输入项) 1. **回执**(`ap_xxxx.json`)—— 签名后的声明。 2. **公钥**(`ap_xxxx.pub`,一个 PEM 文件)—— 与回执一同分发。 3. **(可选)原始输出文件** —— 仅当你还需要证明 输出本身未被更改时才需要。 ### 步骤 1. **重构签名消息。** 回执是对其字段(version, model root, model-root-type, input commitment, output hash, timestamp, log sequence, hardware evidence, log anchor)的规范长度前缀 preimage 进行签名的。该编码是单射的,因此没有两个不同的回执能共享同一个 preimage(进而共享同一个签名)。 2. **检查**该 preimage 相对于公钥的 **Ed25519 签名**。如果验证通过,则回执的内容正是被签名的内容 —— 哪怕只有一个 bit 的改变也会导致此检查失败。 3. **(可选)使用 SHA-256 重新计算输出文件的哈希值**(原始字节,流式处理),并与回执的 `output_hash` 进行比较。如果它们匹配,则说明输出未被更改。 ### 单命令方式 ``` # 仅 signature aetherproof verify ap_xxxx.json # signature + 确认输出文件仍然匹配 aetherproof verify ap_xxxx.json --output original_output.txt # 脚本 / CI:machine-readable,任何失败时以 non-zero 退出 aetherproof verify ap_xxxx.json --output original_output.txt --quiet # -> {"valid": true, "signature_valid": true, "output_unmodified": true} ``` 只有在一切检查无误时退出代码才为 `0`,任何篡改都会返回 `1` —— 因此 `aetherproof verify … && deploy` 在 pipeline 中使用是安全的。 ### 不使用 AetherProof 进行验证(使用任何 Ed25519 库) 由于格式是开放的,任何人都可以使用标准的加密库进行验证 —— 不依赖此工具。在 Python 中使用 `cryptography` 库: ``` import json, hashlib from cryptography.hazmat.primitives.serialization import load_pem_public_key r = json.load(open("ap_xxxx.json")) pub = load_pem_public_key(open("ap_xxxx.pub", "rb").read()) # 为每个字段按顺序重建 injective preimage:":" fields = [ r["receipt_version"], r["model_weight_root"], r["model_root_type"], r["input_commitment"], r["output_hash"], str(r["timestamp_ms"]), str(r["log_sequence"]), json.dumps(r["hw_evidence"], sort_keys=True, separators=(",", ":")), r["log_anchor"], ] preimage = "".join(f"{len(f)}:{f}" for f in fields).encode("utf-8") pub.verify(bytes.fromhex(r["signature"]), preimage) # raises if invalid print("signature OK") # 可选:证明输出文件未被更改 digest = hashlib.sha256(open("original_output.txt", "rb").read()).hexdigest() print("output unmodified:", digest == r["output_hash"]) ``` 这就是整个信任模型:**一个公钥以及一些你可以在任何地方、永久运行的 SHA-256 + Ed25519 数学运算。** ## Agent 链上下文(回执 v1.2) 回执可以选择性地提交至 **命名空间 runtime 上下文** —— 即输出属于哪个 agent 操作、运行或策略决策 —— 并置于签名 *内部*。 这会将回执绑定到其颁发时所针对的确切决策中,因此有效的回执 无法在不同的上下文中被重放。 ``` from aetherproof.core.receipt import Receipt r = Receipt( model_weight_root="...", output_hash="...", signed_extensions={ "org.liminal.agent_chain/v0.1": { "purpose": "generate", "actor_id": "agent:planner", "run_id": "run_42", "policy_decision_id": "pol_7", } }, ) # r.receipt_version 现在为 "1.2";基于 canonicalized # extensions 的 SHA-256 commitment 被折叠进 signing preimage 中 —— 篡改任何字段都会破坏它。 ``` - **空的 extensions → 回执保持为 v1.1,字节完全相同。** 对 现有的回执或验证器没有影响。 - **非空 → v1.2。** 每个扩展的 SHA-256 承诺(RFC 8785 JCS 规范化)被聚合并附加到单射 preimage 中,因此可以 披露或省略一个命名空间,而不会破坏其他命名空间。 这是 AetherProof 方面对应的 [agent 链上下文规范](https://github.com/pulkit6732/aetherproof/issues/1)。 多跳 pipeline 聚合(对每一跳进行签名,识别被篡改的跳)属于 **Signet Layer 3**,并基于此原语构建。 ## 架构(god file) AetherProof 是 **Signet** 技术栈的 **Layer 2**。Signet 在此基础上增加了硬件根、合规包和透明度网络。 ## 许可证 Apache 2.0。使用它,部署它,fork 它,将其嵌入到商业产品中 —— 没有任何限制。完整条款请参见 LICENSE。 **AetherProof 是当你需要防篡改证明时的选择。** **Signet 是当你需要硬件根、合规包和透明度日志时的选择。**
标签:CNCF毕业项目, CVE, 人工智能, 密码学, 手动系统调用, 数字签名, 数据溯源, 用户模式Hook绕过, 逆向工具