跳至主要內容

如何使用零知識證明在以太坊上構建隱私應用程式

零知識證明
隱私
菲利普·克勞斯
EF Builder Growth
2026年5月12日
12 分鐘閱讀

以太坊在設計上是極度公開的。任何擁有區塊鏈瀏覽器的人都可以看到每個地址、餘額、交易、合約呼叫和事件。當你需要可驗證性時,這種透明度非常有用。但當用戶需要投票、申領、提款或證明會員身分,而不希望將每個操作都連結回同一個錢包時,這就會成為一個問題。

匿名會員制是一種可重複使用的模式,為以太坊上一大類隱私應用程式提供動力。人們首先註冊,然後在不透露自己是哪位成員的情況下,證明他們屬於該群體。零知識證明是註冊錢包和操作錢包之間的橋樑,而這座橋樑不會透露是誰跨越了它。

周邊的產品會改變,但隱私骨架保持不變。

透過匿名投票解釋該模式

該模式包含三個部分。一個承諾會註冊每位成員。一棵默克爾樹將這些承諾變成一個群體。一個證明和一個作廢者(nullifier)讓一位成員可以操作一次,而不會透露是哪位成員進行了操作。

第一步:註冊

每位投票者在鏈下建立兩個私密值:秘密(secret)和作廢者(nullifier)。投票者將這些值雜湊成一個公開的承諾,然後在鏈上註冊該承諾。

承諾是公開的註冊紀錄。秘密和作廢者是投票者稍後需要的私密票據(note)。如果遺失了票據,投票者就無法證明會員身分。如果洩漏了票據,其他人可能就可以代替該用戶投票。

因為承諾是一個雜湊,觀察者無法還原其中的私密值。承諾表示「有人註冊了」,但不會透露稍後誰將使用該註冊。

第二步:建立群體

隨著越來越多投票者註冊,應用程式會將他們的承諾收集到一棵默克爾樹中。默克爾樹將一長串的值壓縮成單一雜湊,稱為根(root)。只要更改列表中的任何值,雜湊就會改變,因此根可以作為整個集合防篡改的摘要。

這棵樹就是你的匿名集。如果樹中有十個用戶,觀察者可以將後續的操作縮小到這十個人之一。如果樹中有一萬個用戶,就很難將操作連結到單一個人。一個匿名集很小的隱私應用程式通常不太具有隱私性,即使密碼學是正確的。

第三步:匿名操作

當投票開始時,投票者不應該使用註冊承諾的同一個錢包進行投票。從註冊錢包投票會將投票直接連結回註冊者,從而破壞隱私保護工作。相反地,投票者會建立一個零知識證明。該陳述被編碼為一個電路,表示:「我知道能產生已註冊承諾的私密值,並且我正在揭露這次投票正確的作廢者雜湊。」

該證明能說服驗證者合約該陳述為真。它不會透露秘密、作廢者,或使用了哪個承諾。

作廢者是用來防止重複投票的機制。在提交證明的同時,投票者會發布一個作廢者雜湊。投票合約在接受投票後會儲存該雜湊。如果同一個私密票據再次用於同一次投票,它會產生相同的作廢者雜湊,合約就會拒絕第二次投票。結合證明,這使得合約只知道某個已註冊的投票者操作了一次,而不知道是哪一位。

可重複使用的閘門

同樣的證明與作廢者組合不僅適用於投票。撇開投票的情境,你得到的是一個用於智能合約函式的隱私閘門。

在函式執行之前,合約會檢查默克爾根、驗證證明、確認作廢者雜湊未被使用過,並將公開輸入綁定到正確的應用程式、鏈、投票、申領或提款。如果這些檢查通過,它會將作廢者標記為已使用,並執行函式的其餘部分。

將這個閘門放在投票之前,你就得到了匿名投票。將它放在空投申領之前,你就得到了匿名申領。將它放在提款函式之前,你就得到了混幣器風格提款流程的核心。相同的承諾樹、相同的作廢者概念、相同的證明模式。改變的只有函式主體和周邊的應用程式邏輯。

什麼在哪裡運行

私密工作通常在鏈下進行。用戶儲存票據,客戶端應用程式建立見證並運行證明者來產生證明。索引器會追蹤承諾和默克爾根。捆綁器會在鏈上傳播用戶操作(UserOperation),並由 ERC-4337 代付合約贊助燃料,因此一個全新的錢包不需要先從用戶已知的錢包獲取 ETH。

公開的強制執行發生在鏈上。驗證者合約會檢查證明。應用程式合約會檢查有效的根和未使用的作廢者、儲存作廢者雜湊,並執行公開操作。

敏感的使用者體驗(UX)在於票據的處理。請將秘密和作廢者視為金鑰。不要將它們放入分析、日誌、URL、錯誤報告或一般的伺服器端遙測中。一旦票據洩漏,無論證明有多強大,隱私都會蕩然無存。

工具已經跟上

你不需要手動編寫底層的密碼學程式碼。常見的做法是使用高階零知識語言編寫電路,產生一個 Solidity 驗證者,然後從應用程式合約中呼叫該驗證者。

適合的技術堆疊取決於工作需求。Circom 搭配 snarkjs 是應用程式級別電路行之有效的途徑。Noir 搭配 Barretenberg 是一條較新且對開發者友善的途徑。Halo2 和 gnark 是較低階的電路函式庫。像 RISC Zero 或 SP1 這樣的 zkVM 可以證明一般的程式,但證明的成本可能比小型的自訂電路更高。

對於匿名會員制,在編寫自己的電路之前,請先尋找現有的協定。Semaphore 將群組會員制和基於作廢者的防止重複使用機制打包成合約和 JavaScript 函式庫。對於私密投票和治理,MACI 是專門的途徑,因為它增加了防勾結的特性。成熟的協定通常比新的電路更安全。

僅有證明是不夠的

如果錢包流程洩漏了關聯性,即使是完美的證明也會失效。從錢包 A 註冊,稍後又從錢包 A 進行操作,任何觀察者都能將這些交易連結起來。在操作前夕從錢包 A 轉帳給錢包 B,這筆資金交易也會造成同樣的問題。

這就是為什麼捆綁器和代付合約如此重要。操作錢包應該是全新的,而且它不應該需要從用戶試圖與該操作分開的錢包中接收 ETH。

同樣的問題也存在於鏈下。從同一個 IP 地址、RPC 供應商或工作階段提交註冊和操作交易,可能會削弱電路提供的隱私。前端可能會透過分析、本機儲存和支援日誌發生洩漏。零知識證明隱藏了證明內部的值,但它並不會隱藏交易周圍的所有事物。

公開輸入是隱私應用程式失敗的另一個地方。在電路中標記為公開、作為事件發出、包含在呼叫資料(calldata)中,或由合約儲存的任何內容都是可見的。審查公開輸入時,應像審查 Solidity 合約上的存取控制一樣仔細。

這對開發者帶來了什麼改變

在以太坊上實現隱私是可行的。開發者可以將這些組件組合成真實的應用程式。這個技術堆疊包含:用於私密陳述的電路、用於檢查證明的驗證者、用於公開規則的應用程式合約、用於默克爾資料的索引器,以及用於無關聯提交和燃料贊助的捆綁器加代付合約。

困難的部分在於產品設計、金鑰管理、中繼資料衛生、稽核,以及擴大匿名集。只要其中任何一個環節出錯,證明所提供的隱私就會消失。

進一步閱讀

  1. 零知識證明 (ethereum.org) (在新分頁開啟)
  2. Semaphore 文件 (在新分頁開啟)
  3. MACI 文件 (在新分頁開啟)
  4. Circom 文件 (在新分頁開啟)
  5. Noir 文件 (在新分頁開啟)
  6. Halo2 手冊 (在新分頁開啟)
  7. gnark 文件 (在新分頁開啟)
  8. RISC Zero 文件 (在新分頁開啟)
  9. SP1 文件 (在新分頁開啟)
  10. EIP-4337:透過 EntryPoint 合約實現帳戶抽象化 (在新分頁開啟)