由武汉大学、浙江蚂蚁密算科技有限公司共同研发,提出 Hydra 区块链机密计算环境下通用可信远程证明协议关键构造方法。
该成果受到以下资助:
- 中国网络空间安全协会
- 中国互联网发展基金会
- 第三期网络安全学院学生创新资助计划
Hydra 面向区块链机密计算环境中多类型 TEE 架构并存、证明协议不统一、跨架构互操作验证困难等问题,基于 IETF 远程证明服务标准 RATS,构建了一套通用可信远程证明协议框架。
该框架通过统一设备认证、证明生成、证明验证与链上可信调用流程,实现不同 TEE 架构之间的互操作验证,为数据要素在混合 TEE 环境中的合规、安全流通与价值转化提供技术参考。
基于 IETF RATS 标准,提出一种面向区块链机密计算环境的通用可信远程证明协议。该协议通过统一设备身份认证与证明验证流程,实现异构 TEE 设备在区块链环境中的可信接入与可验证运行。
该协议具备以下特性:
- 支持不同 TEE 架构之间的互操作验证;
- 支持交互式与非交互式协同证明;
- 具备公共可验证性;
- 具备证据透明性;
- 支持无信任验证;
- 支持 TEE 设备的动态批量添加与删除;
- 支撑混合 TEE 环境下数据要素的合规流通、安全共享与价值转化。
Hydra 的主要创新与优势如下:
| 特性 | 说明 |
|---|---|
| 通用性 | 支持多种主流 TEE 架构,适用于异构可信执行环境 |
| 互操作性 | 通过统一远程证明协议实现跨 TEE 架构可信验证 |
| 公共可验证性 | 验证过程可由多方独立完成,降低中心化信任依赖 |
| 证据透明性 | 证明证据与验证结果可链上记录,便于审计与追溯 |
| 无信任验证 | 借助区块链与密码学机制减少对单一验证方的依赖 |
| 动态扩展性 | 支持 TEE 设备批量添加、删除与状态更新 |
| 区块链适配性 | 面向区块链机密计算场景设计,支持智能合约可信调用 |
Hydra 可为区块链机密计算环境提供统一、可验证、可扩展的可信远程证明支撑,适用于以下场景:
- 区块链节点可信接入;
- 机密计算任务可信调度;
- 数据要素可信流通;
- 多 TEE 架构协同验证;
- 智能合约调用前可信状态确认;
- 设备状态链上透明管理;
- 分布式可信基础设施建设。
本项目实现了一个基于 Rust 的三方验证系统,系统中包含三个主要角色:
attester:被验证方,负责生成本地身份信息、签名数据、生成零知识证明并发送给 relying-party。verifier:验证者,负责接收 attester 的身份信息,维护 shrubs tree,生成并更新 attester 的shrubs_path和shrubs_tag。relying-party:依赖方,负责接收 verifier 发布的公共信息,并验证 attester 提交的零知识证明。
项目支持两种运行模式:
passport模式:attester 向 verifier 注册并获取响应信息,然后生成EvidenceReply,由 relying-party 进行零知识证明验证。background_check模式:attester 将签名后的DeviceClientInfor发送给 relying-party,relying-party 再签名后转发给 verifier,由 verifier 验证双方签名。
项目使用的主要技术包括:
- Rust 异步网络通信:
tokio - ECDSA 签名:
k256::ecdsa - 零知识证明:Groth16
- Merkle/shrubs tree 路径计算
- 并行计算:
rayon - 本地二进制序列化存储
项目根目录为:
C:\Users\11197\Documents\New project\hydra
主要目录如下:
hydra
├── attester
│ └── src/main.rs
├── verifier
│ └── src/main.rs
├── relying-party
│ └── src/main.rs
├── hydra-sys
│ └── src/lib.rs
├── Cargo.toml
└── Cargo.lock
各目录作用:
attester:attester 角色的执行程序。verifier:verifier 角色的执行程序。relying-party:relying-party 角色的执行程序。hydra-sys:公共库,存放公共结构体、签名、加密、零知识证明、shrubs tree 相关逻辑。
如果电脑还没有安装 Rust,需要先安装 Rust 工具链。
推荐使用 rustup 安装。安装完成后,在 PowerShell 中执行:
rustc --version
cargo --version如果能正确输出版本号,说明 Rust 安装成功。
打开 PowerShell,进入项目目录:
cd "C:\Users\11197\Documents\New project\hydra"第一次运行前,建议先执行:
cargo check如果依赖完整、代码无错误,会看到类似:
Finished `dev` profile
如果出现 warning,例如:
warning: unused variable
这类 warning 不影响项目运行。
项目中三个角色会分别将自己的本地数据存储在各自目录下,不再统一存储到 hydra-sys 目录。
三个角色的数据目录如下:
attester/workspace-data
verifier/workspace-data
relying-party/workspace-data
attester 每次运行都会创建一个唯一 session 目录,例如:
attester/workspace-data/attester-runs/attester-1779602536325204600-20396-0
该目录中会保存:
attester_key.bindev_infor.bindev_config.bindev_res.binpublic_context.binevidence-*.bin
每次运行 attester 都会生成不同的 session 目录,避免多个 attester 同时运行时互相覆盖数据。
verifier 会将每个 attester 的响应数据保存到:
verifier/workspace-data/verifier-responses
relying-party 会保存 verifier 发送过来的公共上下文:
relying-party/workspace-data/public_context.bin
该文件包含:
- 当前 shrubs tree 的 root
- verifier 的公钥
verifier_pk
如果 verifier 发送新的 root,relying-party 会自动更新并覆盖旧数据。
运行项目时,建议分别打开多个 PowerShell 窗口。
推荐启动顺序:
- 启动 verifier。
- 启动一个或多个 relying-party。
- 启动 attester。
如果端口被占用,会出现类似错误:
通常每个套接字地址(协议/网络地址/端口)只允许使用一次
这说明该端口已经有程序在使用。可以关闭对应窗口,或者换一个端口。
以下示例使用一个 verifier、三个 relying-party。
首先进入项目目录:
cd "C:\Users\11197\Documents\New project\hydra"打开第一个 PowerShell 窗口,运行:
cargo run -p verifier -- 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004参数说明:
127.0.0.1:7001是 verifier 自己监听的地址。127.0.0.1:7002、127.0.0.1:7003、127.0.0.1:7004是三个 relying-party 的地址。
verifier 启动后会监听 attester 和 relying-party 发来的消息。
打开第二个 PowerShell 窗口,运行:
cargo run -p relying-party -- 127.0.0.1:7002 127.0.0.1:7001参数说明:
127.0.0.1:7002是当前 relying-party 自己监听的地址。127.0.0.1:7001是 verifier 的地址。
打开第三个 PowerShell 窗口,运行:
cargo run -p relying-party -- 127.0.0.1:7003 127.0.0.1:7001打开第四个 PowerShell 窗口,运行:
cargo run -p relying-party -- 127.0.0.1:7004 127.0.0.1:7001passport 模式用于完整演示 attester 注册、verifier 响应、attester 生成零知识证明、relying-party 验证证明的流程。
打开新的 PowerShell 窗口,运行:
cargo run -p attester -- passport 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004参数说明:
- 第一个地址
127.0.0.1:7001是 verifier 地址。 - 后面三个地址是 relying-party 地址。
该指令会自动完成以下步骤:
- attester 生成本地密钥。
- attester 构造
DeviceClientInfor。 - attester 将签名后的
DeviceClientInfor发送给 verifier。 - verifier 收集 attester 的 merkle leaf。
- verifier 构建或更新 shrubs tree。
- verifier 为 attester 生成
ResponseDeviceInfor。 - verifier 使用 attester 公钥加密响应信息。
- attester 解密 verifier 返回的响应信息。
- attester 构造并保存
DeviceConfigInfor。 - attester 生成
EvidenceReply。 - attester 将
EvidenceReply发送给三个 relying-party。 - relying-party 验证 attester 的零知识证明。
- attester 保持与 verifier 的连接,继续接收后续更新。
注意:该命令运行后不会立刻退出,因为它会继续保持与 verifier 的 TCP 连接。
如果你想主动断开,可以在 attester 窗口按:
Ctrl + C
两步模式适合演示“先注册,后续再单独生成证明”的场景。
第一步:提交信息给 verifier。
cargo run -p attester -- passport submit 127.0.0.1:7001该命令会输出一个 session 路径,例如:
attester session path: C:\Users\11197\Documents\New project\hydra\attester\workspace-data\attester-runs\attester-xxxx
第一步运行后,attester 会保持与 verifier 的连接,并继续接收 verifier 后续推送的最新 shrubs_path 和 shrubs_tag。
第二步:使用指定 session 生成证明,并发送给 relying-party。
cargo run -p attester -- passport evidence --session "这里填写第一步输出的attester session path" 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004示例:
cargo run -p attester -- passport evidence --session "C:\Users\11197\Documents\New project\hydra\attester\workspace-data\attester-runs\attester-xxxx" 127.0.0.1:7002如果不指定 --session,attester 会默认读取最近一次 session。
但是,如果你同时运行多个 attester,不建议省略 --session,因为最近一次 session 可能被其他 attester 覆盖。
background_check 模式下,attester 不直接向 verifier 提交证明,而是先将签名后的 DeviceClientInfor 发送给 relying-party。
运行命令:
cargo run -p attester -- background_check 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004该模式流程如下:
- attester 生成本地密钥。
- attester 构造
DeviceClientInfor。 - attester 对
DeviceClientInfor进行 ECDSA 签名。 - attester 将签名后的数据发送给 relying-party。
- relying-party 验证 attester 签名。
- relying-party 对该数据再次签名。
- relying-party 将双签名数据转发给 verifier。
- verifier 验证 relying-party 签名和 attester 签名。
可以打开多个 PowerShell 窗口,运行多个 attester,用于模拟多个 attester 同时加入系统。
例如,多次运行:
cargo run -p attester -- passport 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004每个 attester 都会生成独立 session 目录,因此本地数据不会互相覆盖。
但是需要注意:
- 如果使用一条指令模式,attester 会自己使用当前 session,不容易混淆。
- 如果使用两步模式,第二步建议显式指定
--session。 - 如果不指定
--session,程序会读取最近一次 session,多个 attester 同时运行时可能读错。
verifier 会批量收集 attester 的 merkle leaf。
第一次批量处理时,verifier 调用:
create_batch_devices(...)后续有新的 attester 加入时,verifier 调用:
insert_batch_devices(...)每次 shrubs tree 更新后,verifier 都会重新为所有历史 attester 计算:
shrubs_pathshrubs_tag- verifier 签名
sig - 最新
ResponseDeviceInfor
该过程使用 rayon 并行处理,提高多个 attester 场景下的更新效率。
attester 如果保持与 verifier 的连接,就会自动收到更新,并保存到自己的 session 目录。
如果 attester 主动断开连接,那么 verifier 后续无法再主动推送最新路径信息给该 attester。此时如果使用旧的 shrubs_path 和 shrubs_tag 生成 proof,可能导致 relying-party 验证失败。
relying-party 不需要在命令行指定模式。
它会根据收到的消息类型自动判断:
- 收到
PublicContext:保存 verifier 发来的 root 和 verifier 公钥。 - 收到
DeviceClientInfor:按background_check流程处理。 - 收到
EvidenceReply:按passport流程验证零知识证明。
在 passport 模式下,relying-party 验证零知识证明时,会输出 attester 公钥编码。
成功示例:
relying-party proof verification success; attester_pubkey=...
失败示例:
relying-party proof verification failed; attester_pubkey=...
错误示例:
通常每个套接字地址(协议/网络地址/端口)只允许使用一次
原因:该端口已经被其他进程占用。
解决方法:
- 关闭占用该端口的 PowerShell 窗口。
- 或者更换端口,例如把
7002改为7012。
如果运行:
cargo run -p attester -- passport evidence --session "某个旧session路径" 127.0.0.1:7002relying-party 可能输出:
relying-party proof verification failed
常见原因是:
- 该 session 中保存的是旧 root。
- verifier 后续已经插入新节点。
- attester 没有保持连接,因此没有收到最新
shrubs_path和shrubs_tag。
解决方法:
- 保持第一步
passport submit的窗口不要关闭。 - 等待 verifier 更新后,使用同一个 session 再执行第二步。
- 或者直接使用 passport 一条指令模式。
该错误通常表示零知识证明验证时 public inputs 不匹配。
常见原因:
- proof 是用旧 root 生成的。
- relying-party 已经保存了 verifier 最新 root。
- proof 中 public input 数量和当前 root 长度不一致。
当前代码已经将该错误处理为验证失败,不会导致 relying-party 直接崩溃。
一般不会。
因为每次 attester 运行都会创建唯一 session 目录。
但如果使用两步模式,并且第二步不指定 --session,可能会读取最近一次 session,从而读到其他 attester 的数据。
因此,多 attester 测试时建议显式指定:
--session "attester session path"推荐使用以下流程进行完整演示。
第一步,启动 verifier:
cargo run -p verifier -- 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004第二步,启动三个 relying-party:
cargo run -p relying-party -- 127.0.0.1:7002 127.0.0.1:7001cargo run -p relying-party -- 127.0.0.1:7003 127.0.0.1:7001cargo run -p relying-party -- 127.0.0.1:7004 127.0.0.1:7001第三步,运行 passport 模式:
cargo run -p attester -- passport 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004第四步,如需测试 background_check:
cargo run -p attester -- background_check 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004