protect-mcp 收据验证专家 agent 全解:Ed25519 签名、JCS 规范化与哈希链审计实战

发布时间:2026/9/11 20:23:01
protect-mcp 收据验证专家 agent 全解:Ed25519 签名、JCS 规范化与哈希链审计实战
protect-mcp 收据验证专家 agent 全解Ed25519 签名、JCS 规范化与哈希链审计实战【免费下载链接】agentsMulti-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity项目地址: https://gitcode.com/GitHub_Trending/agents24/agents导读本文围绕 protect-mcp 插件中负责收据验证与链审计的专家 agentreceipt-verifier展开讲解其如何基于 Ed25519 签名、RFC 8785 JCS 规范化与哈希链审计对每一次 Claude Code 工具调用的授权决策进行离线、可独立复现的完整性验证。读完本文你将掌握收据格式与验证流程、veritasacta/verify的退出码语义、单收据验证与整链审计的实操命令以及签名不匹配、链断裂、格式损坏三类失败的具体诊断方法。收据验证专家在 protect-mcp 中的定位receipt-verifier是 protect-mcp 插件中专职负责验证的 agent。protect-mcp 的核心链路是Cedar 策略评估 → 工具调用 → Ed25519 签名收据 → 哈希链审计每一次工具调用在PreToolUse阶段被 hooks.json 中的protect-mcp evaluate用 Cedar 策略判定 allow/deny随后在PostToolUse阶段由protect-mcp sign生成签名收据写入./receipts/。而receipt-verifier恰好对应这条链路的末端——它回答这张收据是否可信、这条审计链是否完整。与同目录下的 policy-enforcer.mdCedar 策略编写专家负责事前授权形成互补一个管写规则一个管验证据。从 agent 元数据看receipt-verifier 使用model: sonnet职责描述为Ed25519 签名收据、JCS 规范化、哈希链与离线验证的专家。三条密码学原语收据可信性的地基receipt-verifier 的知识体系建立在下述三个标准之上缺一不可原语标准作用Ed25519RFC 8032Edwards 曲线数字签名32 字节公钥、64 字节签名确定性、高性能、安全性经过充分论证JCSRFC 8785JSON 规范化方案按键的字典序排序对象键产生确定性字节序列SHA-256—用于内容寻址与链链接的哈希函数这里的关键认知是JCS 存在的必要性同一份 JSON 数据可能因键顺序、空白符不同而产生多种合法序列化形式。若直接对原始字符串签名任何无害的格式化改动都会导致验签失败而 JCS 先把 JSON 规整为确定性的字节序列再对该序列签名从而保证逻辑上相同的 JSON 一定得到相同的签名结果。这正是verify-receipt命令执行流程中重建规范形式JCS→ 在规范字节上验签的原因。收据格式一份合法收据长什么样按照 receipt-verifier 的文档一份合法收据应包含以下字段{ receipt_id: rec_hash, receipt_version: 1.0, issuer_id: string, event_time: ISO 8601 UTC, tool_name: string, decision: allow | deny, policy_id: string, policy_digest: sha256:hex, input_hash: sha256:hex, parent_receipt_id: rec_hash | null, public_key: hex 64 chars, signature: hex 128 chars }要点说明receipt_id与parent_receipt_id共同构成哈希链的链接点创世收据链首的parent_receipt_id为null。policy_digest与input_hash用sha256:hex形式记录策略内容与工具输入的指纹。public_key为 64 个 hex 字符即 32 字节公钥signature为 128 个 hex 字符即 64 字节 Ed25519 签名。仓库的测试目录给出了更贴近实现细节的信封结构receipt-schema.json 定义了 protect-mcp0.7.4 收据的 JSON Schemav2 信封其中必需字段为v整数常量 2、typedecision_receipt或gateway_restraint、algorithm常量ed25519、kid、issuer、issued_atdate-time 格式、payload、signature。Schema 描述指出其镜像了draft-farley-acta-signed-receipts决策事实存放在payload中作为一个整体被签名payload内必需tool与decisiondecision取值为allow/deny并可携带reason_code、policy_digest、request_id、spec等可选字段。签名串最小长度为 32。也就是说agent 文档描述的是决策事实模型而 schema 描述的是线缆上的信封序列化两者指向同一套协议。五步验证流程与退出码语义receipt-verifier 将单张收据的验证固化为以下流程解析 JSON提取public_key与signature对其余所有字段构建 JCS 规范形式用公钥在规范字节上验证签名若签名有效沿parent_receipt_id向后回溯检查链完整性。验证命令veritasacta/verify的退出码是程序化的结果契约也是 Agent 解释结果的依据退出码含义Agent 应报告的内容0有效签名校验通过结构良好Verified. Signed by key{pub_key_short}, no tampering detected.1被篡改签名与载荷不匹配Tampered. The signature does not match the payload.2格式损坏结构错误缺字段、类型错Malformed. The receipt is missing required fields or has the wrong structure.这三类退出码在插件命令层被完整继承verify-receipt.md 中/verify-receipt path的执行体正是npx veritasacta/verify $1且明确完全离线运行无网络请求、无厂商查询、不依赖操作者信任。实战一验证单张收据在 Claude Code 中调用/verify-receipt命令对应 verify-receipt.md/verify-receipt ./receipts/2026-04-15T10-30-00Z.json等价于在 Bash 中执行npx veritasacta/verify $1Agent 收到结果后按退出码给出对应报告。文档为三种结果分别给出了标准输出模板验证通过Verified ✓ Receipt: rec_8f92a3b1 Tool: Bash Decision: allow (policy: autoresearch-safe) Signed at: 2026-04-15T10:30:00.000Z Signer: 4437ca56815c0516... Chain link: parentrec_3d1ab7c2 ✓发现被篡改TAMPERED ✗ The signature does not match the payload. This receipt has been modified since it was signed. Receipt ID: rec_8f92a3b1 Expected signer: 4437ca56815c0516... Possible causes: - A field was edited after signing (most common) - The signature was copied from a different receipt - The public key was replaced格式损坏MALFORMED ✗ The file is not a valid Veritas Acta receipt. Missing or invalid fields: list the specific structural issues A valid receipt must include: receipt_id, receipt_version, issuer_id, event_time, tool_name, decision, public_key, signature.实战二审计整条收据链单张收据只能证明这一条决策没被改过而哈希链能证明整段历史没有插入、删除或分叉。/audit-chain命令对应 audit-chain.md负责整链审计/audit-chain # 审计 ./receipts/ 下全部收据 /audit-chain --last 50 # 只验证最近 50 条 /audit-chain --dir /var/log/receipts # 指定其他目录其执行流程为列出目标目录下所有*.json→ 按event_time排序建立时间顺序 → 逐条独立验签 → 确认每条非创世收据的parent_receipt_id与上一条的receipt_id一致 → 报告所有失败及诊断信息。底层实现# 默认全部收据 RECEIPT_DIR${2:-./receipts} # 只审计最近 N 条 if [ -n $1 ] [ $1 --last ]; then N$2 ls -1 $RECEIPT_DIR/*.json | sort | tail -n $N | xargs npx veritasacta/verify else npx veritasacta/verify $RECEIPT_DIR/*.json fi链链接验证可显式使用--chain标志npx veritasacta/verify --chain $RECEIPT_DIR/*.json审计报告同样有三种形态。全链通过Audit chain verification: PASSED Scanned: 247 receipts Time range: 2026-04-12T08:00:00Z to 2026-04-15T10:30:00Z Chain head: rec_8f92a3b1 Chain root: rec_0a1b2c3d Signatures: 247/247 valid ✓ Chain links: 246/246 correct ✓ Parent breaks: 0 Signer keys: 1 unique (4437ca56815c0516...)发现链断裂结构性攻击此时所有签名都有效但某条收据的parent_receipt_id与预期不符例如第 #142 条声称父节点是rec_8d4f2e91而期望的是rec_6b5c1a8d。这意味着收据本身都是真实签发的但链结构被破坏——可能是插入了伪造节点、删除了中间节点或签名者引用了错误的父节点。诊断方法检查被声称的父节点是否存在、被期望的父节点的后继是否缺失、与外部见证或备份比对。发现单条被篡改载荷攻击签名 246/247 有效链链接反而完好说明是某条收据签发后被改了内容属于载荷篡改事件而非结构攻击需与已知良好副本比对找出被改字段。文档还给出了明确的运行时机建议发布前确认开发链无篡改、安全审计时向审计方展示链完整性、事件后核实日志未被篡改、CI/CD 中周期性执行以捕获静默损坏、合规审查前提供持续完整性证据。验证失败的三种根因诊断当验证失败时receipt-verifier 要求 Agent 必须精确说明失败原因而不是笼统地报验证失败签名不匹配Signature mismatch——signature字段无法用public_key在载荷的规范形式上验签说明收据在签名后被修改过被签名的部分中任何字段都可能是被改动的目标。这是攻击者签后改数的直接证据。链断裂Chain break——某条收据的parent_receipt_id与期望的前一条receipt_id不匹配。三种可能在两条合法收据之间插入了新收据、从链中删除了收据、链发生分叉后只保留了其中一个分支。格式损坏Malformed——缺少必需字段或类型错误。这要么是签名者的 bug要么是伪造者对格式理解不透彻而产出的伪劣赝品。面向非专家的类比解释文档为向非技术读者解释提供了三组经典类比可在任何报告场景中复用签名 信封上的火漆印任何人都能看见并核验封印与寄件人一致信封一旦被拆开封印即破损。JCS 规范化 密封前先按字母序整理词句使封印图案可预测、可复现。哈希链 账本的连续页码有人撕掉一页页码立刻出现跳号。不可动摇的原则绝不伪造receipt-verifier 有一条硬性纪律永远不生成或修改收据即使是为了演示。伪造一张收据哪怕明显是假的都会侵蚀信任模型本身。用户若想了解被篡改收据长什么样正确的做法是用描述哪个字段可能被改动的方式在用户自己的收据上演示验证失败而绝不能由 Agent 亲手产出被篡改的收据。这条原则与验证可信性的职责互为表里——验证者的公信力恰恰建立在验证者不参与签名之上。仓库中的实现证据测试如何锁定验证行为protect-mcp 的 test/ 目录为上述全部行为提供了可复现的测试证据是理解验证语义的最佳旁证往返测试run-tests.sh需 node ≥ 18 与 python3执行 8 个用例Read 放行exit 0、Bash git status放行、Bash rm -rf /拒绝exit 2、Write 拒绝、PostToolUse 签名产出收据文件、收据符合 schema、veritasacta/verify接受收据、篡改收据被拒绝exit 1。其中第 8 个用例是关键的回归防线在已签名的收据上翻转decision字段Ed25519 签名必然失效验证器必须返回 1 而非 0。静态校验verify-fixtures.sh仅需 python3不执行任何 protect-mcp 命令只验证 fixture 是合法 JSON、pre-tool fixture 包含tool_name/tool_input/session_id必需字段、schema 引用真实的 JSON Schema draft、Cedar 策略文件非空。退出码 77 表示依赖缺失而跳过autotools 约定。收据形状签名输入样例 posttool-signing-input.json 展示了签名前需采集的事实tool_name、tool_input、tool_output、session_id、decision、policy_id与信封 schema 中的payload字段一一呼应。策略形状test-policy.cedar 展示了 protect-mcp ≥ 0.7.0 实际求值的实体形状——principal Agent::id、action Action::MCP::Tool::call、resource Tool::toolName工具输入位于context.input并注明 0.5.5 的求值器存在已知缺陷旧式Action::Read形状的策略仅看似生效。Cedar 的forbid具有权威性即使某条permit匹配只要forbid命中如命令包含rm -rf、dd、mkfs、shred决策即为拒绝。与插件整体架构的关系从 protect-mcp README 的架构图可以看清验证所在的完整流水线工具调用Bash、Edit、Write、Read、WebFetch…触发PreToolUsehook执行npx protect-mcp0.7.4 evaluate按 principal / action / resource / context 做 Cedar 判定——deny 则 exit 2 拦截permit 则放行工具执行或不执行PostToolUsehook 执行npx protect-mcp0.7.4 sign把tool_name、input_hash、output_hash、decision、policy_id、policy_digest、parent_receipt_id、public_key、signature写成./receipts/timestamp.json任意一方可用npx veritasacta/verify receipts/*.json离线验证单条或整链。因此验证能力具备三个特性离线无网络、无厂商查询、无账户、免信任不依赖操作者诚实、可组合/verify-receipt与/audit-chain分别覆盖单点与全局两个粒度。在需要向审计方证明开发与发布全流程未被篡改的场景中这条 evaluate → sign → verify 的闭环即是核心证据链。相关资源专家定义receipt-verifier.md本文主体、policy-enforcer.mdCedar 策略编写命令实现verify-receipt.md、audit-chain.md运行时接线hooks.json协议与测试receipt-schema.json、test/README.md、test-policy.cedar完整安装与使用protect-mcp README 及 protect-mcp-setup 技能需要说明的是本文依据的协议字段模型收据字段、验证步骤、退出码来自 receipt-verifier 文档与仓库 schemaveritasacta/verify的具体实现细节与draft-farley-acta-signed-receipts的完整规范以对应协议文档为准。若需在真实项目中使用请以本仓库文档中的命令与当前 npm 包行为为准进行验证。【免费下载链接】agentsMulti-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity项目地址: https://gitcode.com/GitHub_Trending/agents24/agents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考