📢 Gate廣場 #NERO发帖挑战# 秀觀點贏大獎活動火熱開啓!
Gate NERO生態周來襲!發帖秀出NERO項目洞察和活動實用攻略,瓜分30,000NERO!
💰️ 15位優質發帖用戶 * 2,000枚NERO每人
如何參與:
1️⃣ 調研NERO項目
對NERO的基本面、社區治理、發展目標、代幣經濟模型等方面進行研究,分享你對項目的深度研究。
2️⃣ 參與並分享真實體驗
參與NERO生態周相關活動,並曬出你的參與截圖、收益圖或實用教程。可以是收益展示、簡明易懂的新手攻略、小竅門,也可以是行情點位分析,內容詳實優先。
3️⃣ 鼓勵帶新互動
如果你的帖子吸引到他人參與活動,或者有好友評論“已參與/已交易”,將大幅提升你的獲獎概率!
NERO熱門活動(帖文需附以下活動連結):
NERO Chain (NERO) 生態周:Gate 已上線 NERO 現貨交易,爲回饋平台用戶,HODLer Airdrop、Launchpool、CandyDrop、餘幣寶已上線 NERO,邀您體驗。參與攻略見公告:https://www.gate.com/announcements/article/46284
高質量帖子Tips:
教程越詳細、圖片越直觀、互動量越高,獲獎幾率越大!
市場見解獨到、真實參與經歷、有帶新互動者,評選將優先考慮。
帖子需原創,字數不少於250字,且需獲得至少3條有效互動
ERC-7520草案詳解:zk-SNARK公共輸入溢位攻擊防護
作者:Beosin安全研究專家Saya & Bryce
1. 什麼是零知識證明
零知識證明(Zero-Knowledge Proof,後文簡寫ZKP)是一種密碼學概念,它可以用來證明某個聲明的真實性,而無需透露有關該聲明的任何具體信息。在零知識證明中,證明者可以向驗證者證明某個陳述是正確的,而驗證者只會得到一個結果:要麼接受該陳述的真實性,要麼拒絕它,而無需了解證明的具體細節。
這個概念可以用一個簡單的例子來解釋。假設有兩個人,一個是證明者和一個是驗證者。證明者想向驗證者證明自己知道一個秘密的密碼,而不洩漏密碼本身。在傳統的方式中,證明者可能會告訴驗證者密碼是什麼,但在零知識證明中,證明者可以使用特殊的協議來向驗證者證明他知道密碼的正確性,而不洩露密碼本身。
目前常見的零知識證明系統演算法包括zk-SNARKs、zk-STARKs、BulletProofs等。
2. ZKP在區塊鏈中的應用
在區塊鏈技術中,ZKP有多種應用,例如提升隱私、改善可擴展性和安全性等。以下是ZKP在區塊鏈中的一些關鍵應用:
1 隱私保護:
區塊鏈是公共的,這意味著任何人都可以查看鏈上的所有交易。然而,有時候,用戶可能希望保持他們的交易資訊保密。 ZKP允許用戶證明他們擁有足夠的資金進行交易,同時不必公開他們的資金總額。這大大增強了用戶的隱私保護。例如,Zcash是一種使用零知識證明技術的加密貨幣,它允許用戶隱藏交易的發送者、接收者和金額。
2 計算壓縮與區塊鏈擴容:
區塊鏈的可擴展性是一個挑戰,尤其是在大規模應用中。 ZKP可以用於減輕節點的負擔,提高整個系統的可擴展性。透過使用ZKP驗證交易的有效性,節點無需查看完整的交易歷史記錄,從而減少了儲存和處理的負擔,目前應用最廣泛的ZK Rollup是一種擴展性解決方案,旨在提高以太坊及其他區塊鍊網路的吞吐量和效率。它結合了Rollup和ZKP技術的優勢,提供了高效能的去中心化應用程式(DApps)擴展方案。在傳統的以太坊網路上,每個交易都需要被驗證和記錄在區塊鏈上,這導致了交易處理的延遲和高成本。而ZK Rollup透過將大量的交易批量處理並壓縮為單一區塊,ZKP則用於證明批量交易的有效性,從而確保交易的正確性和安全性。
3 身份驗證:
零知識證明可以用於驗證使用者的身份而無需透露敏感的個人資訊。例如,一個人可以使用零知識證明向網路證明他們滿足某個特定的年齡要求或擁有某種特定的證書,而無需揭示他們的確切年齡或其他身分資訊。
4 去中心化儲存:
伺服器可以向用戶證明他們的資料已妥善保存,並且不洩露資料的任何內容。
總的來說,**區塊鏈的零知識證明在隱私保護、運算壓縮與擴容、身份驗證、去中心化儲存等方面有著廣泛的應用。它為區塊鏈技術提供了更多的功能和選擇,推動了區塊鏈在不同領域的發展和應用。 **
3. ZKP應用程式中的雙花攻擊
zk-SNARK(Zero-Knowledge Succinct Non-Interactive Argument of Knowledge)是一種基於零知識證明的技術,可以在不洩露真實資訊的情況下證明某個聲明的真實性。它是一種非常有效率的零知識證明技術,可以在非常短的時間內產生和驗證證明,同時保護隱私和安全性,所以應用非常廣泛。但是,伴隨著應用程式的擴展,其安全性也越來越受到關注。我們在不久前就曾發現了其通用漏洞:ZKP專案中如果未正確校驗verify函數中參數input的取值範圍,攻擊者可以偽造多個input通過校驗,造成雙花攻擊。這種攻擊影響範圍非常廣,涉及多個zk-SNARK演算法包括:groth16、plonk等,且solidity、js等多種開發語言均存在此漏洞。此漏洞最開始由poma在零知識證明計畫Semaphore上首次發現,並給出了兩筆成功實施的交易範例,具體如下圖所示:
該漏洞具體的攻擊原理是,如果要在以太坊中產生和驗證zk-SNARK證明,需要使用F_p-arithmetic 有限域橢圓曲線電路,其中p值用於確定橢圓曲線有限域的範圍,所以電路的input取值範圍為[0,1,…,p-1]。不同的曲線擁有不同的p值:
EIP-196 中定義的BN254 曲線(也稱為ALT_BN128 曲線):
p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
circom2 引入了兩個新的質數,即BLS12-381曲線:
p = 52435875175126190479447740508185965837690552500527637822603658699938581184513
以及plonk2:
18446744069414584321
,則必須傳回 true。 /// 如果證明未通過所有檢查(即 /// 證明無效),則必須傳回 false。 /// @param 證明 A zk-SNARK。 /// @param input 伴隨證明的公共輸入。 /// @param verifyKeyId 證明對應的驗證金鑰的唯一識別碼(此驗證者 /// 合約已知)。 /// @return result 驗證計算的結果。 True /// 若證明有效;否則為假。函數驗證(uint256 [] calldata 證明,uint256 [] calldata 輸入,bytes32 VerificationKeyId) 外部回傳(布林結果);}
其中,零知識證明proof、inputs變數類型都為uint256[],該變數類型是目前ZKP演算法中橢圓曲線運算最常用的,但是該介面中也未增加對應的安全防護,因此同樣存在雙花攻擊的巨大安全隱憂。
5. ERC-7520解決方案
Beosin根據上述問題,提出了EIP-7520防範這種安全風險,具體為以太坊生態中所有使用了zk技術的DApp專案方在compliant verifier contract 中,都必須實現該介面從而使用規範統一而又安全的方式對所有input進行有效範圍校驗,具體介面如下:
pragma Solidity ^0.5.6;/// @title EIP-XXXX zk-SNARK public input Verifier Standard/// 注意:此介面的ERC-165 識別碼為0xXXXXXXXX。/// ⚠️ TODO:計算介面識別碼interface EIP7520face /* is ERC165 & ERC1922 */ { /// @notice 檢查輸入的參數是否在標量欄位內 /// @dev /// 如果輸入通過範圍檢查(即輸入 /// 有效),則必須傳回 true。 /// 如果輸入未通過範圍檢查(即 /// 輸入無效),則必須傳回 false。 /// @param input 伴隨證明的公共輸入。 /// @param p 曲線附帶的公共輸入。 function verifyPublicInput(uint256[] inputs,uint256 p) 外部回傳 (bool result);}
verifyPublicInput函數是這個標準的核心,涉及到的參數具體意義如下:
以下將比較實現與未實現EIP-7520介面的兩種情況下,針對該攻擊的不同表現,以向各位項目方表明風險:
1 假設我們在不呼叫本eip介面verifyPublicInput的情況下,直接使用verify合約程式碼進行證明驗證,具體程式碼如下:
function verify(uint[]記憶體輸入,Proof記憶體證明)內部視圖回傳(uint) {VerifyingKey記憶體vk = verifyingKey(); require(input.length + 1 == vk.IC.length,"驗證器錯誤輸入"); // 計算線性組合 vk_x Pairing.G1Point 記憶體 vk_x = Pairing.G1Point(0, 0); for (uint i = 0; i < input.length; i++) vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[i + 1], input) [i] )); vk_x = 配對.addition(vk_x, vk.IC [0] );如果(!Pairing.pairingProd4(Pairing.negate(proof.A),proof.B,vk.alfa1,vk.beta2,vk_x,vk.gamma2,proof.C,vk.delta2))返回1;返回0;}
原始的證明驗證通過的實驗結果截圖:
同時,可以偽造如下4個證明同樣可以通過驗證,造成雙花攻擊:
使用其中一個偽造的證明,驗證結果如下圖所示:
2 如果呼叫了本eip中的verifyPublicInput接口,上述偽造的證明則會驗證失敗,部分合約程式碼如下,其餘詳細部分可以參考Reference Implementation:
函數 verifyx(uint[] 記憶體輸入,Proof 記憶體證明,bytes32 VerificationKeyId,uint256 p) public returns (uint){ require(verifyPublicInput(inputs,p),"verifier-over-snark-scalar-field"); require(verify(inputs,proof,verificationKeyId),"驗證失敗"); return true;}function verifyPublicInput(uint256[] inputs,uint256 p) 內部視圖 returns (bool) { for (uint i = 0; i < input.length; i++) { require(input < p,"verifier-gte-snark -標量場");返回真;}
實驗結果如下圖所示:
綜上,可以發現如果不使用本介面對公共訊號值進行取值範圍的有效性校驗,那麼**可能存在雙花攻擊風險。 **