第二章 架构总览:远程证明系统三大角色与工作流程

远程证明这东西,说白了就是让一台机器向另一台机器证明「我是我,我没被篡改」。听起来简单,但落地时坑特别多。我刚开始接触这个领域时,光理解 Attester、Verifier、Relying Party 这三个角色之间的关系,就绕了好几天。

这一章,咱们把架构拆开来看。你搞懂了骨架,后面排查故障才有方向。

2.1 核心角色:谁在证明?谁在验证?谁在信任?

远程证明系统里,只有三个玩家。不多不少。

角色 英文名 一句话定义 我见过的典型实体
证明者 Attester 需要自证清白的设备或进程 TPM 芯片、机密计算 enclave、启动中的 BIOS
验证者 Verifier 检查证据是否可信的裁判 远程证明服务端、云平台 attestation 服务
依赖方 Relying Party 根据验证结果做决策的业务方 VPN 网关、密钥管理系统、应用服务器

关键认知: Relying Party 不直接参与证明过程。它只问 Verifier 一句话:「这家伙可信吗?」Verifier 说可信,它就放行。这个解耦设计,是整套架构的精华。

2.2 工作流程:一次完整的远程证明长什么样?

我习惯把流程分成四个阶段。每个阶段都可能出问题,咱们后面排查时会反复提到这些节点。

  1. 挑战阶段(Challenge) — Verifier 给 Attester 扔一个随机数,防止重放攻击。
  2. 证据收集阶段(Evidence Collection) — Attester 收集自身的度量值(比如 PCR 值、代码哈希),并用私钥签名。
  3. 验证阶段(Verification) — Verifier 检查签名、比对参考值、评估证据是否新鲜。
  4. 决策阶段(Decision) — Verifier 把结果(Pass/Fail + 属性声明)发给 Relying Party。

嗯,这里要注意:第 2 步和第 3 步之间,经常出现「证据格式不匹配」的问题。我曾经遇到过一个案例,Attester 用 TPM 2.0 格式生成 quote,但 Verifier 只认 TPM 1.2 的格式,结果验证永远失败。排查了两天才发现是协议版本没对齐。

2.3 架构图:一张图看懂数据流向

下面这张 SVG 图,是我自己画的标准参考架构。你把它存下来,后面每章都会用到。

远程证明系统架构图 远程证明系统架构 — 三大角色与数据流 Attester 证明者(设备/Enclave) Verifier 验证者(裁判服务) Relying Party 依赖方(业务系统) ① Challenge(随机数) ② Evidence(签名度量值) ③ 验证结果(Pass/Fail) 📌 数据流说明 • 第①步:Verifier 生成一次性随机数(Nonce),防止重放攻击。 • 第②步:Attester 收集 PCR/TCB 度量值,用私钥签名后返回。 • 第③步:Verifier 验证签名、比对参考值、检查 Nonce 一致性。 • 第④步(隐含):Relying Party 根据结果决定是否放行业务请求。 • 整个过程中,Relying Party 不直接接触 Attester 的原始证据。

我的经验: 排查故障时,先确认数据流走到哪一步了。如果 Attester 根本没收到 Challenge,那就是网络或握手问题。如果收到了但返回的 Evidence 格式不对,那就是 Attester 侧配置问题。按图索骥,效率最高。

2.4 角色间的信任模型

你想想看,Verifier 凭什么相信 Attester 发来的证据?Relying Party 又凭什么相信 Verifier 给出的结论?

这里涉及两个信任锚点:

  • Attester → Verifier: 基于硬件绑定的身份密钥。比如 TPM 的 Endorsement Key(EK)或 Attestation Key(AK)。这些密钥在制造时注入,理论上不可导出。
  • Verifier → Relying Party: 基于 Verifier 的数字签名。Relying Party 需要预先配置 Verifier 的根证书或公钥。

我记得有一次线上故障,Relying Party 一直拒绝放行,查到最后发现是 Verifier 的证书过期了。Relying Party 端没有及时更新信任锚,导致所有验证结果都被判定为无效。嗯,这种问题在运维中特别容易忽略。

2.5 常见架构变体

实际部署时,架构不会完全按教科书来。我见过几种常见变体:

变体类型 描述 适用场景
本地验证 Verifier 和 Relying Party 在同一进程内 嵌入式设备、单机可信启动
云端验证 Verifier 作为独立服务部署在云端 大规模设备管理、机密计算
链式证明 Attester 先证明给中间代理,代理再转发给 Verifier 跨网络隔离环境、IoT 网关
嵌套证明 一个 Attester 内部再运行子 Attester 容器内嵌套 Enclave、虚拟化场景

避坑指南: 我曾经在链式证明架构中踩过一个大坑。中间代理在转发 Evidence 时,不小心修改了 Nonce 字段,导致 Verifier 侧 Nonce 不匹配,验证全部失败。排查了整整一天才发现是代理层的序列化/反序列化逻辑有 bug。所以,任何中间层都要做「透传完整性校验」。

2.6 工作流程的时序细节

咱们把时序再拉近一点。一次标准的远程证明,在代码层面大概长这样:

// 伪代码:Attester 侧
1. recv(challenge_nonce)          // 接收 Verifier 发来的随机数
2. pcr_values = read_pcr()        // 读取平台配置寄存器
3. evidence = sign(pcr_values + challenge_nonce, private_key)  // 签名
4. send(evidence)                 // 发送证据

// 伪代码:Verifier 侧
1. nonce = generate_nonce()       // 生成随机数
2. send(nonce)                    // 发送挑战
3. recv(evidence)                 // 接收证据
4. if verify_signature(evidence, public_key) == false:
       return FAIL
5. if extract_nonce(evidence) != nonce:
       return FAIL
6. if match_reference_values(evidence) == false:
       return FAIL
7. return PASS

你看,逻辑其实不复杂。但每个步骤都可能出幺蛾子。比如第 2 步读 PCR,如果 TPM 驱动没加载,读出来的就是空值。第 4 步验签,如果公钥和私钥不匹配,那更是直接挂掉。

我个人习惯在 Attester 和 Verifier 两侧都加详细的日志,把每一步的输入输出都打出来。这样出问题时,直接看日志就能定位到是哪个环节断了。

2.7 本章小结

远程证明的架构,核心就是三个角色、四个步骤。Attester 负责自证,Verifier 负责裁判,Relying Party 负责决策。数据流从 Challenge 开始,到 Decision 结束,中间不能有篡改和遗漏。