惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

大猫的无限游戏
大猫的无限游戏
Webroot Blog
Webroot Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
Threat Research - Cisco Blogs
V2EX - 技术
V2EX - 技术
L
LINUX DO - 热门话题
Google DeepMind News
Google DeepMind News
Recorded Future
Recorded Future
S
Schneier on Security
I
InfoQ
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
The GitHub Blog
The GitHub Blog
S
Security @ Cisco Blogs
O
OpenAI News
W
WeLiveSecurity
Vercel News
Vercel News
阮一峰的网络日志
阮一峰的网络日志
Simon Willison's Weblog
Simon Willison's Weblog
人人都是产品经理
人人都是产品经理
Cloudbric
Cloudbric
The Last Watchdog
The Last Watchdog
The Hacker News
The Hacker News
Google Online Security Blog
Google Online Security Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
GbyAI
GbyAI
NISL@THU
NISL@THU
T
Tailwind CSS Blog
V
Visual Studio Blog
PCI Perspectives
PCI Perspectives
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Jina AI
Jina AI
D
DataBreaches.Net
B
Blog RSS Feed
N
News and Events Feed by Topic
N
News and Events Feed by Topic
H
Heimdal Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
腾讯CDC
Latest news
Latest news
V
Vulnerabilities – Threatpost
Hacker News: Ask HN
Hacker News: Ask HN
WordPress大学
WordPress大学
V
V2EX
aimingoo的专栏
aimingoo的专栏
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Register - Security
The Register - Security
Help Net Security
Help Net Security

smallyu的博客

为什么买的加密货币一定要去中心化 RISC-V 虚拟机无法代替 EVM 虚拟机 Polkadot 的 Existential Deposit 机制错在哪里 利息,套利,交易策略,金融市场 LayerZero 从来不挑战比特币的地位 默认参数引起的以太坊节点运行错误 硬件钱包与资产安全 预测市场比币圈更赌场 为什么去中心化的跨链桥不可能实现 我对于 AI 时代的答案 不要投资任何隐私币 区块链技术世界的三大真理 以太坊 AA 钱包的致命问题是什么 基于 AI 语义执行的 MCP 区块链的设计 一个集成 Geth 和 CometBFT 的兼容层 我的加密货币定投策略(二) DeFi 基础: 理解 AMM 定价机制 Go 语言 GMP 调度器的原理是什么 Web3 项目分析计划 对 Psyche Network 项目的分析 continuation 教程: 理解 CPS 如何开发一个比特币符文(Runes)协议 比特币脚本开发教程 我从王垠的计算机科学视频班学到了什么 区块链技术面试题(2025年版) Rust 语言容易让新手困惑的一个“过度优化” Solana 智能合约开发教程 (1) 尝试开发一个最小 EVM 虚拟机 一个 Web3 打赏系统的设计 鼓吹 Cursor 的人技术能力都差 关于 Code Review 的礼节 假如启动一个新的以太坊 PoS 网络 发行加密货币的最好方式 所有 BFT 共识的区块链都是中心化的 对 2025 年区块链行业的预测 Restaking 项目的经济难题 如何看懂任意区块链项目的技术架构 为什么不要做以太坊的二次开发 为什么不要做智能合约开发和 DeFi 开发 我的加密货币定投策略(一) PoS 类型的区块链如何处理分叉 Ethereum Casper 为什么需要 EIP-7251 区块链中的 PBFT 不需要第二次投票 开发者的思维方式 发币的核心要点 炒币投资的小 tips 为什么说 PoW 比 PoS 更加去中心化 牛市对普通人来说意味着什么 如何健康地远程工作 为什么比特币不用概率加密函数 程序员的 “服从权威” 心理 区块链技术面试题 如何区分公有链和联盟链 对 Layer 2 项目创业想法的回复 对区块链共识机制的理解 Pebbling Game 鹅卵石游戏 PDP 文件证明的局限性 不要小瞧 ChatGPT 为什么炒币不是一个好主意 一种在区块链上生成随机数的机制 为什么以太坊的私钥计算不可逆 关于以太坊的私钥碰撞 “猜均值的2/3” dApp 游戏设计 Proof of Storage/Space/Replication 的区别 Proofs of Retrievability 文件证明的含义 对 S-PDP 文件证明的示例和解释 我的加密货币交易机器人 对区块链行业的见闻 随机确认块的共识机制 VRF + BFT 共识引起交易失败的问题 为什么要重视编程思想 对 Web 3.0 的理解 GitBook 好用吗? 一种区块链节点存储扩容的方式 一种基于“自我中心主义”的共识机制 链表常见算法题及解析 基于 Multi-Linked List 的区块链设想 理解哈希函数与序列化 联盟链比公有链差在哪儿 在 Dijkstra 算法中保存路径 为什么数字货币使用区块链是政治问题 区块链:下一代数字身份认证体系的基石 网页技术能实现 3D 建模吗? 给区块链一个定义 从 Erlang 开始了解 Actor 模型 一种侧边导航栏的交互方式 Rust 的 ownership 是什么? Haskell 中的 Monad 是什么? 浅析 Libra 背后的区块链技术 对区块链的理性认识 Rust 基础语法概述 基于 Java 的爬虫框架 WebCollector Kotlin:简化版的 Scala JavaScript 有关联数组吗? 主流编程语言的异常处理机制 Go 语言基本语法 Scala 语法基础 用 Scala 改写 Java 浅度实践 Python 获取海贼王更新信息 HTML5 音乐可视化
基于 ZK 的链上身份系统设计
2025-04-30 · via smallyu的博客

2025-04-30

我给这个系统取名 zkgate.fun,主要想发挥零知识证明的特性,结合区块链做个小工具。关键功能是实现,用户证明自己属于某一个群组,但是不需要暴露自己真实的链上身份。

目前的设想是这样,管理员首先有一个名单列表,可以是以太坊地址的数组,然后根据这个地址列表,计算出一个 Merkle Root Hash。接着把这个 root hash 提交到智能合约上。处于这个名单中的人,可以使用 Circom 电路的 proving key,来给自己生成一个 zk proof,随后将 zk proof 提交到智能合约上。

在智能合约上,会使用 Circom 电路生成的 verifier.sol,对收到的 zk proof 进行验证,判断用于生成 zk proof 的地址,是否在 Merkle Root Hash 中,最后将判断结果返回。

这样的话,管理员不需要公开自己的群组中有哪些地址,属于群组中的地址也不需要声明自己的身份,只需要提交零知识证明生成的 zk proof,就可以证明自己真的归属于这个群组。我接下来会具体在技术上实现这个设计。


更新 v0.1.0 版本 (2025.05.09)

首先要纠正之前设计中的一个错误的地方,管理员必须要公开自己群组的地址列表,否则无法根据地址列表来生成 Merkle Tree,用户也无法根据树结构,来找到自己地址所在的节点位置、生成路径证明。

其次是很高兴地说,现在跑通了一个非常初级的 Demo(smallyunet/zkgate-demo),这个 Demo 功能并不完善,甚至没有办法在电路中验证地址的所有权,但至少是一个工具链路层面的跑通。

具体实现是这样:

  1. 有一个 链下程序 来根据地址列表,以及自己的地址,生成 zk 电路的 inputs.json,这个输入文件包含了 Merkle Root Hash 和验证节点位置所需要的路径
  2. 根据 电路代码 来编译出一些 二进制文件,这些编译后的产物是用来生成 witness 文件的
  3. 基于公开的 ptau 文件 生成 .zkey 文件
  4. 从 .zkey 文件中导出 proof.json, public.json, verification_key.json,这 3 个 json 文件可以做链下离线验证,证明 prove 的有效性
  5. 从 .zkey 文件中导出 .sol 文件,也就是智能合约代码,部署到链上
  6. 拿着 prove.json 文件和 public.json 文件的内容,作为 参数 调用合约的 verifyProof函数,如果 prove 有效则返回 true,否则返回 false

假如一个地址不在群组列表中,有两种情况:

  1. 试图用一个不在群组列表中的 地址 生成 inputs.json,然后拿着 inputs.json 去根据电路生成 prove,会直接被电路拒绝报错
  2. 试图用一些假的 prove 参数 提交到链上做验证,最终无法通过链上验证

那么目前这个最初级版本的 Demo,问题在于,构建 prove 使用的是明文地址,比如:

const members = [
  "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
  "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
  "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
];

const proofKey = toField(members[0]);
const { siblings } = await tree.find(proofKey);

这个语句的含义是在让 zk 电路判断,members[0] 是否属于 members 数组构建出来的树结构,这显然是属于的。如果想要用不属于群组的地址构建 prove,只需要替换一下 proofKey 指向的地址:

const nonMemberAddress = "0x1234567890123456789012345678901234567890";
const proofKey = toField(nonMemberAddress);
const { siblings } = await tree.find(proofKey);

也就是说,members 列表必须是公开的,而现在的程序只能判断一个地址在不在 members 里面,但即使 members[0] 不是我的地址,我也能用来构建一个合法的 prove。那还要 zk 干嘛?

所以下一步要解决的问题,是让用户用私钥对某个消息进行签名,然后在 zk 电路中根据签名 recover 出地址,接着判断 recover 出来的地址是否属于 members 数组。

这个过程是不是听起来简单?可实际上用 zk 电路来 recover 出一个 ECDSA 签名算法的地址,别说复杂度非常高,难度就像用乐高搭核电站一样。难怪人们都说,搞 zk 真的很掉头发。


更新 v0.2.0 版本(2025.05.13)

这个版本解决了验证地址所有权的问题,基本思路是让 zk 证明和地址所有权的证明分开,链下用 zk 证明地址的路径在 Merkle Root 上,链上需要用户提交用私钥对 root 的签名,并且将签名提交到链上。然后合约 recover 出签名的地址,跟 zk 电路的 prove 中包含的地址信息对比。

1. zk prove 包含地址信息 -> 链上验证 zk prove -> 得知 zk prove 中的地址信息
2. 用私钥对 root 签名 -> 链上得到签名 -> recover 出签名对应的地址信息

3. 判断 zk prove 中的地址 == 签名 recover 出的地址

演示代码具体改动的地方有:

  1. offchain 部分的代码不需要变动,生成 inputs.json 的脚本中 inputs 里已经有 key 的信息了
  2. 电路代码中,需要把 inputs 中的 key 变为 public
  3. 合约代码需要接受用户的 签名 作为参数,并且得到 recover 出的地址,将这个地址与 proof key 进行对比
  4. 调用合约的脚本,需要用私钥对 root 进行签名,并且把签名数据作为参数调用合约

到此为止,zkgate.fun 实现的功能是,群组管理员不必在链上公开自己的群组成员信息,只需要提交 Merkle Root Hash 到链上。对于群组内的成员,需要完整的成员列表,以及自己地址对应私钥签名后的信息,就可以生成 zk prove 去链上,证明自己确实是群组内的成员。

在这个过程中,使用 zk 唯一隐藏掉的信息,是群组成员的完整信息不必上链公开,只需要一个 Merkle Root Hash。而用户的地址目前无法隐藏,必须提交到链上用于验证。


更新(2025.05.14)

有一个现有的、以太坊基金会支持的、工具链和生态都已经比较成熟的 zk 协议,同样是用来做身份验证的项目,叫 Semaphore,官网是这个,可以直接在上面体验一下包含前端界面的 Demo:

在 zkgate.fun 前面两个版本的迭代中,没有选择 Semaphore 使用 EdDSA 账户体系的方案,主要是不想脱离以太坊的账户体系,也不想放弃 ECDSA,而实际上只有 EdDSA 是 zk 友好的,可以使用 Poseidon Hash 签名,zk 电路中也能对签名进行验证,不需要 “链下签名、链上 recover” 这种丑陋的实现方式。

不得不说,从个人学习的角度,虽然没几天的时间,但是我已经大概理解了 zk(工具链)的操作过程。从行业前沿的角度,我仅凭个人力量不可能做的比 Semaphore 更好。即使 zkgate.fun 进一步开发出前端界面、可视化地演示出具体的交互过程,也顶多就是 Semaphore 的这个 Demo 的样子,而且技术上没有 Semaphore 硬核。

所以 zkgate.fun 这个项目不再继续开发,域名一年后会自动到期,不再续费。