Last active
December 6, 2021 14:30
-
-
Save obeliskgolem/cdc79d50e6d55180b647a4353055e72d to your computer and use it in GitHub Desktop.
Another way to solve `zkhack-soundness-of-music`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Just noticed that in the verifier program, there are no checks against the commited points. | |
especially the pairing that checks P == H*Z: | |
``` | |
let d = E::pairing( | |
(pk + proof.pi_input) + (pk + proof.pi_input) + proof.pi_output.mul(-E::Fr::one()).into(), | |
E::G2Affine::prime_subgroup_generator(), | |
) == E::pairing(proof.pi_H, setup.rho_Z); | |
``` | |
We can make use of this. Let's construct H = 0, in which case P will also be 0. | |
In order to make P = 0, we just need to make sure the private inputs exactly cancel out the public inputs. | |
P = 2 * \rho * (IP_1(\tau) * x + IP_2(\tau) * y + IP_3(\tau) * z) - \rho * (OP_1(\tau) * x + OP_2(\tau) * y + OP_3(\tau) * z) | |
Let the second part equals zero, we get pi_output == pi_output_prime = [0] on G1 | |
then we set pi_input = [- (IP_1(\tau) * x + IP_2(\tau) * y)] on G1, so `pk + pi_input` equals the point at infinity. | |
(well, actually in order to pass the proof of knowledge check, we can't just set `pi_input` like that. but, we can just fake public inputs, that's even easier.) | |
That's it! | |
Here is the prover code which generates a fake proof. | |
``` | |
pub fn prove_alter<E: PairingEngine>( | |
public_inputs: &[E::Fr], | |
private_inputs_len: usize, | |
setup: &Setup<E>, | |
) -> Proof<E> { | |
let mut fake_pub_inputs = vec![]; | |
let mut fake_pri_inputs = vec![]; | |
for i in 0..public_inputs.len() { | |
fake_pub_inputs.push(public_inputs[i].neg()); | |
} | |
for _ in 0..private_inputs_len { | |
fake_pri_inputs.push(E::Fr::zero()); | |
} | |
let mut private_input_polynomials = E::G1Projective::zero(); | |
let mut private_input_polynomials_prime = E::G1Projective::zero(); | |
for (private_input, private_input_polynomial, private_input_polynomial_prime) in izip!( | |
fake_pub_inputs.iter().chain(fake_pri_inputs.iter()), | |
setup.inputs.iter(), | |
setup.inputs_prime.iter() | |
) { | |
private_input_polynomials += private_input_polynomial.mul(*private_input); | |
private_input_polynomials_prime += private_input_polynomial_prime.mul(*private_input); | |
} | |
Proof::<E> { | |
pi_input: private_input_polynomials.into(), | |
pi_input_prime: private_input_polynomials_prime.into(), | |
pi_output: E::G1Affine::zero(), | |
pi_output_prime: E::G1Affine::zero(), | |
pi_K: E::G1Affine::zero(), | |
pi_H: E::G1Affine::zero(), | |
} | |
} | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment