#Gate 2025 Semi-Year Community Gala# voting is in progress! 🔥
Gate Square TOP 40 Creator Leaderboard is out
🙌 Vote to support your favorite creators: www.gate.com/activities/community-vote
Earn Votes by completing daily [Square] tasks. 30 delivered Votes = 1 lucky draw chance!
🎁 Win prizes like iPhone 16 Pro Max, Golden Bull Sculpture, Futures Voucher, and hot tokens.
The more you support, the higher your chances!
Vote to support creators now and win big!
https://www.gate.com/announcements/article/45974
Detailed explanation of ERC-7520 draft: zk-SNARK public input overflow attack protection
Author: Beosin security research experts Saya & Bryce
1. What is zero-knowledge proof
Zero-Knowledge Proof (ZKP) is a cryptographic concept that can be used to prove the authenticity of a statement without revealing any specific information about the statement. In a zero-knowledge proof, the prover can prove to the verifier that a certain statement is true, and the verifier only gets one result: either accept the statement as true or reject it, without knowing the specific details of the proof.
This concept can be explained with a simple example. Suppose there are two people, one is the prover and one is the verifier. The prover wants to prove to the verifier that he knows a secret password without revealing the password itself. In the traditional way, the prover might tell the verifier what the password is, but in zero-knowledge proof, the prover can use a special protocol to prove to the verifier that he knows the correctness of the password without revealing the password itself.
Currently, common zero-knowledge proof system algorithms include zk-SNARKs, zk-STARKs, BulletProofs, etc.
2. Application of ZKP in blockchain
In blockchain technology, ZKP has a variety of applications, such as improving privacy, improving scalability and security, etc. Here are some key applications of ZKP in blockchain:
1 Privacy Protection:
The blockchain is public, meaning anyone can view all transactions on the chain. Sometimes, however, users may wish to keep their transaction information private. ZKP allows users to prove that they have sufficient funds to trade without having to disclose their total funds. This greatly enhances user privacy protection. For example, Zcash is a cryptocurrency that uses zero-knowledge proof technology, which allows users to hide the sender, receiver, and amount of a transaction.
2 Computational compression and blockchain expansion:
Blockchain scalability is a challenge, especially in large-scale applications. ZKP can be used to reduce the burden on nodes and improve the scalability of the entire system. By using ZKP to verify the validity of transactions, nodes do not need to view the complete transaction history, thereby reducing the burden of storage and processing. ZK Rollup, currently the most widely used, is a scalability solution designed to improve Ethereum and other areas. Throughput and efficiency of blockchain networks. It combines the advantages of Rollup and ZKP technologies to provide high-performance decentralized application (DApps) expansion solutions. On the traditional Ethereum network, each transaction needs to be verified and recorded on the blockchain, which results in delays and high costs in transaction processing. ZK Rollup batches and compresses a large number of transactions into a single block, and ZKP is used to prove the validity of batch transactions to ensure the correctness and security of transactions.
3 Authentication:
Zero-knowledge proofs can be used to verify a user’s identity without revealing sensitive personal information. For example, a person can use zero-knowledge proofs to prove to the network that they meet a certain age requirement or possess a certain certification without revealing their exact age or other identifying information.
4 Decentralized Storage:
The server can prove to users that their data is being kept securely and that no content of the data is leaked.
In general, **blockchain's zero-knowledge proof has wide applications in privacy protection, computing compression and expansion, identity verification, decentralized storage, etc. It provides more functions and options for blockchain technology and promotes the development and application of blockchain in different fields. **
3. Double-spending attack in ZKP applications
zk-SNARK (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge) is a technology based on zero-knowledge proof that can prove the authenticity of a statement without revealing real information. It is a very efficient zero-knowledge proof technology that can generate and verify proofs in a very short time while protecting privacy and security, so it is widely used. However, with the expansion of applications, its security has attracted more and more attention. We discovered its general vulnerability not long ago: if the value range of the parameter input in the verify function is not correctly verified in the ZKP project, an attacker can forge multiple inputs to pass verification, causing a double-spending attack. The impact of this attack is very wide, involving multiple zk-SNARK algorithms including: groth16, plonk, etc., and this vulnerability exists in many development languages such as solidity and js. This vulnerability was first discovered by poma on the zero-knowledge proof project Semaphore, and two examples of successfully implemented transactions were given, as shown in the figure below:
The specific attack principle of this vulnerability is that if you want to generate and verify the zk-SNARK proof in Ethereum, you need to use the F_p-arithmetic finite field elliptic curve circuit, where the p value is used to determine the range of the elliptic curve finite field, so the circuit The input value range is [0,1,…,p-1]. Different curves have different p-values:
BN254 curve defined in EIP-196 (also known as ALT_BN128 curve):
p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
circom2 introduces two new primes, the BLS12-381 curves:
p = 52435875175126190479447740508185965837690552500527637822603658699938581184513
and plink2:
18446744069414584321
Semaphore later confirmed and fixed the vulnerability, and zk libraries such as ZoKrates and snarkjs also made emergency repairs simultaneously. However, Beosin security researchers found that there is currently no unified solution to this problem. For example, the Semaphore protocol writes constraints into the pairing library. The valid range of data is not explicitly verified in the outer business logic; the contract code generated by circom and Tornado.Cash explicitly verify SNARK_SCALAR_FIELD in the verify function. This is a confusing and inconsistent solution. It may cause trouble and security risks to many new zk DApp project parties, so we hope to use a standardized way to solve this problem.
4. Double spend attack in ERC-1922
Currently, Ethereum has a zk-related standard EIP-1922, which introduces the Verify contract standard interface for verifying zk-SNARK. The specific code is as follows:
pragma solidity ^0.5.6;/// @title EIP-XXXX zk-SNARK Verifier Standard/// @dev See /// Note: the ERC-165 identifier for this interface is 0xXXXXXXXX./// ⚠️ TODO: Calculate interface identifierinterface ERC1922 /* is ERC165 */ { /// @notice Checks the arguments of Proof, through elliptic curve /// pairing functions. /// @dev /// MUST return true if Proof passes all checks (i.e. the Proof is /// valid). /// MUST return false if the Proof does not pass all checks (i.e. if the /// Proof is invalid). /// @param proof A zk-SNARK. /// @param inputs Public inputs which accompany Proof. /// @param verificationKeyId A unique identifier (known to this verifier /// contract) for the Verification Key to which Proof corresponds. /// @return result The result of the verification calculation. True /// if Proof is valid; false otherwise. function verify(uint256[] calldata proof, uint256[] calldata inputs, bytes32 verificationKeyId) external returns (bool result);}
Among them, the zero-knowledge proof proof and inputs variable types are uint256[]. This variable type is currently the most commonly used elliptic curve operation in the ZKP algorithm. However, the corresponding security protection is not added to this interface, so double-spending attacks also exist. Huge safety hazard.
5. ERC-7520 Solution
Based on the above issues, Beosin proposed EIP-7520 to prevent this kind of security risk. Specifically, all DApp projects using zk technology in the Ethereum ecosystem must implement this interface in the compliant verifier contract to use unified and safe standards. The method performs valid range verification on all inputs. The specific interface is as follows:
pragma solidity ^0.5.6;/// @title EIP-XXXX zk-SNARK public inputs Verifier Standard/// Note: the ERC-165 identifier for this interface is 0xXXXXXXXX./// ⚠️ TODO: Calculate interface identifierinterface EIP7520 /* is ERC165 & ERC1922 */ { /// @notice Checks the arguments of Inputs are within the scalar field /// @dev /// MUST return true if Inputs passes range check (i.e. the Inputs are /// valid). /// MUST return false if the Inputs does not pass range check (i.e. if the /// Inputs are invalid). /// @param inputs Public inputs which accompany Proof. /// @param p Public input which accompany the curve. function verifyPublicInput(uint256[] inputs,uint256 p) external returns (bool result);}
The verifyPublicInput function is the core of this standard. The specific meanings of the parameters involved are as follows:
The following will compare the two situations of implementing and not implementing the EIP-7520 interface, aiming at the different manifestations of this attack, to indicate the risks to the project parties:
1 Assume that we directly use the verify contract code for verification without calling the verifyPublicInput of this eip interface. The specific code is as follows:
function verify(uint[] memory input, Proof memory proof) internal view returns (uint) { VerifyingKey memory vk = verifyingKey(); require(input.length + 1 == vk.IC.length,"verifier-bad-input"); // Compute the linear combination vk_x Pairing.G1Point memory 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 = Pairing.addition(vk_x, vk.IC [0] ); if (!Pairing.pairingProd4( Pairing.negate(proof.A), proof.B, vk.alfa1, vk.beta2, vk_x, vk.gamma2, proof.C, vk.delta2 )) return 1; return 0;}
Screenshot of the original experimental results proving that the verification passed:
At the same time, the following four certificates can be forged and can also pass verification, causing a double-spending attack:
Using one of the forged proofs, the verification results are as shown below:
2 If the verifyPublicInput interface in this eip is called, the above forged proof will fail to verify. Part of the contract code is as follows. For the remaining details, please refer to Reference Implementation:
function verifyx(uint[] memory inputs, Proof memory proof, bytes32 verificationKeyId,uint256 p) public returns (uint){ require(verifyPublicInput(inputs,p),"verifier-over-snark-scalar-field"); require(verify(inputs,proof,verificationKeyId),"verify fail"); return true;}function verifyPublicInput(uint256[] inputs,uint256 p) internal view returns (bool) { for (uint i = 0; i < input.length; i++) { require(input < p,"verifier-gte-snark-scalar-field"); } return true;}
The experimental results are shown in the figure below:
In summary, it can be found that if this interface is not used to verify the validity of the public signal value range, there may be a risk of double-spend attacks. **