Pedersen commitment equality proof
This is a zeroknowledge proof that two distinct curve points C1 and C2 are both Pedersen commitments to the same integer value m. The curve points are not equal because the blinding factors are different. This is implemented in the FRP cryptography library using a standard proof technique called a ChaumPedersen proof.
The contents of a ChaumPedersen proof are as follows:

 Public (verifier) inputs C1 = mG + r1H and C2 = mG + r2H
 Private (prover) inputs m, r1 and r2
 Prover generates:
 Three new random values r3, r4, and r5
 The Pedersen commitment C3 = r3G + r4H and C4 = r3G + r5H
 A noninteractive “challenge” c = SHA256(C1, C2, C3, C4)
 Integer values mod p (the prime order of the elliptic curve group): z1 = c m + r3 and z2 = c r1 + r4 and z3 = c r2 + r5
 The proof sent to the verifier contains C3, C4, z1, z2, and z3. The verifier checks:
 C3 + c * C1= z1 G + z2H
 C4 + c * C2 = z1G + z3H
Generating the proof requires 4 scalar multiplications on the elliptic curve (about 60 µs) and verifying this proof requires 6 scalar multiplications (about 90 µs). The size of the proof is two curve points and three scalars, or approximately 160 bytes.
There is also a version of this protocol for proving equality of more than two Pedersen commitments. The input is a list of curve points C1,…,Cn that all commit to the same integer value m, using distinct blinding factors r1,…,rn. The simple way to implement this protocol is to reuse the ChaumPedersen proof and create n – 1 (pairwise) Pedersen equality proofs on each pair (C1, Ci). However, a more efficient method uses a collisionresistant hash function H (e.g. SHA256) and a 128bit prime p, and operates as follows:
 Output a ChaumPedersen proof for the first pair C1 and C2
 Compute k = H(C1,…,Cn) and ai = H(k, i) mod p
 Compute Di = ai(Ci – C1) and zi = ai(ri – r1) for each i = 3 to n
 Compute D = D3 + … + Dn and z = z3 + … + zn
 Output a ChaumPedersen proof that D is a Pedersen commitment to 0, using blinding factor z.
The total size of this proof is two ChaumPedersen proofs (just 320 bytes) and the cost of proof generation/verification for large n is approximately the cost of two ChaumPedersen proofs (60 / 90 µs) plus n additional 128bit scalar multiplications (8 µs each).
Associated functions:
 pedersen_equality_prove([uint64_t] m, [curve_point] C1, [uint256_t] r1, [curve_point] C2, [uint256_t] r2)
 pedersen_equality_verify([string] proof, [curve_point] C1, [curve_point] C2)
 pedersen_equality_list_prove([uint64_t] m, [curve_point*] point_list, [uint256_t*] blind_list)
 pedersen_equality_list_verify([string] proof, [curve_point*] point_list)