其他
Beosin安全研究 | ERC-7520草案详解:zk-SNARK公共输入溢出攻击防护
本文作者:Beosin安全研究专家Saya & Bryce
1. 什么是零知识证明
2. ZKP在区块链中的应用
3. ZKP应用中的双花攻击
https://github.com/semaphore-protocol/semaphore/issues/16
p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
p = 52435875175126190479447740508185965837690552500527637822603658699938581184513
18446744069414584321
4. ERC-1922中的双花攻击
pragma solidity ^0.5.6;
/// @title EIP-XXXX zk-SNARK Verifier Standard
/// @dev See https://github.com/EYBlockchain/zksnark-verifier-standard
/// Note: the ERC-165 identifier for this interface is 0xXXXXXXXX.
/// ⚠️ TODO: Calculate interface identifier
interface 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);
}
5. ERC-7520解决方案
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 identifier
interface 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);
}
inputs :定义为 uint256[] 类型,代表了ZKP项目中verify函数涉及到的公共信号参数
p :定义为uint256 类型,该值对应算法中使用的椭圆曲线的p值
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;
}
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;
}