跳至主要内容

零知識證明(ZKP):從理論到實踐

· 閱讀時間約 14 分鐘
w0x7ce
MySelf

发布于 2025-07-28 20:55:50(微信公众号导出记录)。

本文来自公众号后台的“导出文章内容”功能。博客正文由导出长图进行本地 OCR 转写,并保留原始排版图用于逐段核对。

原文链接:查看原文

OCR 转写有效文字约 6255 字;代码、流程图和版式以文末原始排版图为准。

正文(本地 OCR 转写)

零知罐明(Zero-KnowLedge Proof)是密研學中一项革命性的技街。它允許一方(明者)向

另一方(睡證者)證明白己知道某個秘密,但在整個交互通程中,除了“我知道這個移密“這一事實 外,不泄靠任何照於秘密本身的内客。 這项技病的精粹在的解决一個根本矛昏:如何在不交出数據的前提下,罐明数的真實性。本文链偿 最经典的理输模型人手,结合一咽您可以镜手操作的Python代碼胃验,深入割析ZKP的核心原理。 生活例[] 以下有一鼠影知的政事,速结零红批想的的若干重要阻念·盐事最早出JoJaCuc QLisquatr及网事餐 故事中·小静数现洞穴中某南魔洁严的衡門溶望·六星形入口在一街,射良闲有度法门网断·阿最想 短小春是否已知族增就,但小静很注重私通,不希望泄露难能予问服·也不想全世界知道涂有增就之事 南人分9路入口左右雨除通道骤示九A路·日路·首先,阿最在洞口外,待小静速人润内·小筝自行请择行A A· 路成E路·但问基不准扇拥小排所遇为问·特强,阿醋行入洞穴·均句随提城出A路成B路·表期着望小静由 站方底返团·假老小群值官知道赠·我很基速成,因为团坐越机所属不基同一线路·效也可以鼠門通进 半境富温中越初小群速入的方度·看面入重推以上进程·比如睡错20次:期小都葵重量全部型巧谈正殖方向 望目的氨率板小 為2分21 所以·看小都通植多次提阿层所逼的方肉逐回·所阿鲨可以推斯·小都损可键x道理道· 以下考准第三方的觀监·国使优选月黎附载温题的胰膜·预影所见的整假进程,键期所见本只有阿能城 「A1」小基花A落能因:或网最院「B1小聊能B整退回·此精片段授器由需人共误鲁强(耗露小静贝阴酸 事首商时多次输中网层将语族率入、日的次序),谈百對第三万雨言,不具就服力,即阿出箱此向第三 小静出 方避明小都知睡增號·事宽上·即受终形换成现境在网藏身劳董视布周,因角离人可第一早已候调辉拍好· 但是·若阿聚在前摄硬第·蒸接按质硬第项A碳B,用温定不再零知货·该跌择影可能足以淡第三方, 群知通踏赋·其小群超初的意旅完全相反·不运,赠码的密端学中,「硬策」以购再惠生成额赏作,期似放一枚范果已陷定好的段 ,仁款范是(由其随提硬子决定)签有疑第主人冠道·名阿最的硬带實擦是以比法速作·财组定又国瘦力零知藏旅定,因为南人又有 可核共所急造「官聪:结果·情以使册能过趣整生成器调图真使第不网,前者不會向世人老露小静知速赔號 道有另一楼位法·小群以得一次官陵已可前可着错财自己知通结赋·首不湿露·方法是-雨人一网走人河口·然接同膜目送小群治A路 走·淘有原逐折返,但得目路油团·如此·小样公特巴肩向最證明自己知道赠殖,直准有告知可脂暗·不类出模指利容非零知诺:若 效·如出·小都量法控断何人得如始扬有增硬之事

一、核心思想奥三大展性

要理解ZKP,最直觀的方式是通通“阿里巴巴润穴”道四逐典故事。 場景:一個退形润穴。左右南條通道(A路,B路),深處有一扇需麦暗然才能打购的魔法門。

  • 證明者(小静):聲械地知道网門的暗號。

  • 湿者(阿):想璀诏此事,但不想知溢暗號。

盤明额如下:

1.阿是在洞外等待,小释须自进入洞穴,随楼選握A路或B络。

2.阿层跑後走到润口,随喊出一储方向,例如“静促A路出来!“

3.如果小静知道暗然,地塘能打需中間的門,微网最指定的A路返回。

4.如果她不知道暗號,她只有56%的模率(即她一開始就运了A路)能完成挑载。

將遗個遥程重桓20次,小静每次都成功的概率,對於一個作驿卷来催有(1/2)20(的百离分之

一)。因此,阿最可以高度建信小静知道暗號,但自始至終,网殿没有学到關於暗號的任何信息。

道個故事揭示了ZKP必须具偏的三大属性:

1.完備性(Completeness):若障述为真,誠置的明者能成功就服验腿考。

2.健全性(Soundness):若康述為假,作整的超明者乎不可噬放骗验者。

3.零知鳞性(Zero-KnowLedge):验退者除了“骤述為真"外,学不到任何额外信息。

二、理输经典:来自继基百科的計算例

除了直载的故事,ZKP继立在實的数学瓣题之上、 额例1:解激剧数用题 这是身份稳额中的一值提典连用。

  • 場景:小静想向同證时她知道密碼×。但不想池露X

  • 公信息:一個大質数p,一個生成元g,以及小静的公输y=gxpmodp。找到x被為

是計算上困醒的。

  • 明(简化版):

1.承:小还握一随握数r,計算C=grpmodp,逆将C送给阿。

2,挑哦:阿题碳地向小释提出一因挑:要么“公限r,要么“公開(x+r)pnodp-1”。

3.回离奥脑:

  • 若间要r,小解就绘出r。闫睡grpmodp是否等於小帮一始给的C.

  • 若网变(×+r)pmodp-1,小静就给出遗储值(我何稍之為s)。阿聚独

gspnodp 是否等龄 Ccdotypmodp. 这個家之所以安全,是因為如果小静不知道x,她只能提前测阿碳的挑為之率情。例如,如 果她弹储回答r,她就無法在被間到(x+r)時给出正確答案。每一输地作算成功的概率只有56%。 能例2:大面的哈密硬增度题

  • 场景:一個(由很多點和退桶成的纲络),如果能找到一条路程,恰好通签個點一次,遗

格路就叫*哈密顿琅”。找到这核一跟是NP完全周显,計算上非常困。小孵整科她知道 圖G的一個哈密畅璃。

  • 量明像:

1.承諾:小静创注一阅置G结捐完全相同但贴被打副的折圆H(和為同图)。然

後她對图H的信息造行“加密示诺”,阿照法视,但小蔚白己也思法再慕改。

2.挑:同醒髓碳提周:“虚明H和G是同横的”或“幅展示H的哈密顿環”。

3.回鹿奥脑量:

  • 若被問及同性,小耐就解密整因图H亚給出顾贴烈医鼠低,阿能可以验造。

  • 若被問及哈密顿琅,小只解密横成璟的那些温,阿酸可以看到H中璀置存在一锰璟。

因為小静不知道阿酸會問账困問题,所以她焦法同時终造一惬同机的图和一個不相關的哈密顿璃。而 對同来整,冬一检他只能得到其中一個信品,永逼焦法游“H的瑞“和*H奥G的對癌“拼须 起来,谈而焦法得知原圆G的哈密顿環。

三、现代實践:一個可助手操作的代码實融

理很侵雅,但现代ZKP系(如worLdcoin、zk-RoLLups)是如何谨作的?我何通通一個完整 的Pythan宽驰来模凝其核心提制:Merkle树和 NuLLifier。 實驰率信:必裂的 Python 代碍 請在同一個资料夹中創建以下三但文件。 文件1:merkle_tree.py Python qT1useu luodut def hash_data(data): if not isinstance(data, bytes): data - data.encode['utf-8*) return hashlib.sha256(data) hexdigest() class MerkleTree: def init_(self, leaves): self.leaves = sorted([hash_data(leaf) for leaf in leaves]) def _build_tree(self, leaves): if not leaves: return [None] tree, current_level = [leaves] , leaves while len(current_level) > 1: next_Level = [] left = current_level[1] rlght = current_Level[1+1] If 1 + 1 < len{current_leve parent = hash_data(left + right) if left < right else next_level ,append (parent) tree.append (next_Level) current_level = next_level return tree det get_root(selt): relurn self.tree[-1l[@] if self.tree and self.tree[-1l else No def gct_proof(self, leaf_data): leaf_hash = hash_data( Leaf_data) Iry: index = self.leaves.index(leaf_hash) cxccpt valucError: rcturn Nonc proof = [] [ur level in range{len(self.tree] - 1): is_right = index % 2 1= θ sibling_1dx = 1ndex - 1 1f 1s_right else 1ndex + 1 31 if sibling_idx < len(self.tree[level]): proof.append(self. 32 else: proof.append(self.tree[level][index]) 33 34 index //= 2 return proof 35 def print_tree(self): 36 print(- Merkle Tree Structure ---) 37 for i, level in enumerate(self.tree): 38 print(f"Level {i} (Leaves):" if i == θ else f"Level {i}:") 6E for node in level: print(f" {node}") G

文件2:zkp_simulation.py Python import os, hashlib def hash_data(data): if not isinstance(data, bytes): data = data.encode(*utf-8′) return hashlib.sha256(data) .hexdigest() class Identity: def init(self, name) : self.name = name self.secret = hash_data(os.urandom(32)) self.commitment = hash_data(self.secret) 文件3:technical_deep_dive.py(主通行文件) Python from merkle_tree import MerkleTree, hash_data from zkp_simulation import Identity # PART l: System Initialization print("="*8θ+"\nPART1:如何徙每個人的秘密,計算出「P口的總验證碼(MerkleF alice,bob, charlie, david = Identity("Alice"), Identity("Bob"), Ident. identities = [alice, bob, charlie, david] print("..·系統中的4位合法用户及其數撼 for id in identities: print(f"[{id.name}]\n-私密 secret:{id.secret}\n·公 commitme 10 tree = MerkleTree([id.secret for id in identities]) tree.print_tree() merkle_root = tree.get_root() 2 print(f"\n===>最懿計算出的F口魏驗證碼(MerkleRoot)是:{merkle_root}\n 14 # PART 2 & 2.5: Membership Proof print("="*8θ+"\nPART2:成員資格證明(不同的路徨,相同的山頂)\n"+"=*8θ) for user in [alice, bob]: 16 17 user_secret = user.secret 18 user_proof_path = tree.get_proof(user_secret) print(f"---{user.name}的證明退程---") 19 print(f"{user.name} 的私密 secret:{user_secret}") 20 21 current_hash = hash_data(user_secret) 2 2 print(f"step θ({user.name}):起始哈希值:{current_hash[:1o]}...") 23 for i, sibling_hash in enumerate(user_proof_path): 2 4 print(f"step [i+l} ({user.name}):都居 {sibling_hash[:lo]}... 25 current_hash = hash_data(current_hash + sibling_hash) if curre 2 6 2 7 print(f"{user.name}的最計算果:{current_hash}") 28 print(f"结果是否匹配? ==> {current_hash == merkle_root}\n") 2 9 30 # PART 3: Nullifier Logic print("="*8θ+"\nPART 3:如何實現「一次性领」(NulLifier)\n"+"="*80) used_nullifiers_db = set() scenarios=[("VoTE_A",“第一次投票"),("VoTE_A",“再次投票"),("GET_GIFT for action_id, desc in scenarios: print(f".-场景:Alice {desc}({action_id})-.-") 36 nullifier = hash_data(alice.secret + action_id) 3 7 print(f"===>計算出的'领粪證’(Nullifier):{nullifier}") 38 39 if nullifier in used_nullifiers_db: print(f"植查記薄:{nullifier[:l0]}...已存在。") 40 print(“结果:拒!此證已被使用。\n") 4 1 42 else: print(f"检查記簿:{nullifier[:l0]}...是全新的。") 43 print("果:接受!將其加入記錄簿。\n") 4 4 used_nullifiers_db.add(nullifier) 45 print(f"最终的記錄簿:{used_nullifiers_db}") 通行奥解镇 在終端中運行pythontechnical_deep_dive.py,將看到一個群的計算日,它展示了:

1.群體指紋的生成:系統如何4位用户的私密信息,通遍唇唇哈希,最終生成一個代表了整個

群體的、公闻的Merkle Root。

2.匿名成員證明:Alice和Bob如何使用各自完全不同的秘密和證明路径,通通相同的計算逛

辑,最終都得到了與公開的MerkleRoot完全相同的結果,徙而證明了自己的成員資格,但 没有暴露自己是。

3.防止重復操作:Nullifier機制如何通遍Hash(秘密+事件ID),為每一次操作生成一個獨

一無二的、匿名的“一次性票根”,有效防止了匿名状態下的作行為。

原始排版图

零知識證明(ZKP):從理論到實踐:微信公众号导出原始排版图