in src/cg21/cg21_rp_pi_affg.c [489:743]
int Piaffg_Verify(PAILLIER_private_key *verifier_paillier_priv, PAILLIER_public_key *prover_paillier_pub,
PEDERSEN_PRIV *pedersen_priv, octet *C, octet *D, octet *X, octet *Y,
Piaffg_COMMITS *commits, octet *E, Piaffg_PROOFS *proofs){
// ------------ VARIABLE DEFINITION ---------
int fail;
int equal;
ECP_SECP256K1 G;
ECP_SECP256K1 P;
ECP_SECP256K1 Q;
BIG_1024_58 e[FFLEN_2048];
BIG_1024_58 n[FFLEN_2048];
BIG_1024_58 p_proof[FFLEN_2048];
BIG_1024_58 q_proof[FFLEN_2048];
BIG_1024_58 p_gt[FFLEN_2048];
BIG_1024_58 q_gt[FFLEN_2048];
BIG_1024_58 ws1[FFLEN_2048];
BIG_1024_58 ws2[FFLEN_2048];
BIG_1024_58 ws3[FFLEN_2048];
BIG_1024_58 CC[2 * FFLEN_2048];
BIG_1024_58 DD[2 * FFLEN_2048];
BIG_1024_58 dws[2 * FFLEN_2048];
BIG_512_60 ws4[FFLEN_4096];
BIG_512_60 ws5[HFLEN_4096];
BIG_512_60 ws6[FFLEN_4096];
BIG_512_60 dws2[2 * FFLEN_4096];
BIG_1024_58 q[HFLEN_2048]; //256 bits
BIG_1024_58 q2[FFLEN_2048]; //q^2
BIG_1024_58 q3[FFLEN_2048]; //q^3
BIG_1024_58 q5[FFLEN_2048]; //q^5
BIG_1024_58 q7[FFLEN_2048]; //q^7
char oct1[2 * FS_2048];
octet OCT1 = {0, sizeof(oct1), oct1};
char oct2[2 * FS_2048];
octet OCT2 = {0, sizeof(oct2), oct2};
char oct3[2 * FS_2048];
octet OCT3 = {0, sizeof(oct3), oct3};
// Curve order
CG21_GET_CURVE_ORDER(q);
// Compute q^2, q^3, q^5, q^7
FF_2048_sqr(q2, q, HFLEN_2048);
FF_2048_mul(q3, q, q2, HFLEN_2048);
FF_2048_mul(q5, q3, q2, FFLEN_2048);
FF_2048_mul(q7, q5, q2, FFLEN_2048);
// ------------ CHECK 'z1' IS IN [0, ..., q^3] and 'z2' IS IN [0, ..., q^7]------------
if (FF_2048_comp(proofs->z1, q3, FFLEN_2048) > 0 || FF_2048_comp(proofs->z2, q7, FFLEN_2048) > 0)
{
return Piaffg_INVALID_RANGE;
}
OCT_copy(&OCT1, E);
OCT_pad(&OCT1, FS_2048);
FF_2048_fromOctet(e, &OCT1, FFLEN_2048);
// ------------ VALIDATES THE PROOF - PART1 ----------
// Split check s^z1 * t^z3 * S^(-e) == E mod PQ using CRT
CG21_Pedersen_verify(p_proof, pedersen_priv, proofs->z1, proofs->z3, commits->S, e, pedersen_priv->mod.p, false);
CG21_Pedersen_verify(q_proof, pedersen_priv, proofs->z1, proofs->z3, commits->S, e, pedersen_priv->mod.q, false);
FF_2048_dmod(p_gt, commits->E, pedersen_priv->mod.p, HFLEN_2048);
FF_2048_dmod(q_gt, commits->E, pedersen_priv->mod.q, HFLEN_2048);
fail = (FF_2048_comp(p_gt, p_proof, HFLEN_2048) != 0) || (FF_2048_comp(q_gt, q_proof, HFLEN_2048) != 0);
if (fail)
{
// Clean memory
FF_2048_zero(p_gt, HFLEN_2048);
FF_2048_zero(q_gt, HFLEN_2048);
FF_2048_zero(p_proof, HFLEN_2048);
FF_2048_zero(q_proof, HFLEN_2048);
return Piaffg_INVALID_PROOF_P1;
}
// ------------ VALIDATES THE PROOF - PART2 ----------
// Split check s^z2 * t^z4 * T^(-e) == F mod PQ using CRT
CG21_Pedersen_verify(p_proof, pedersen_priv, proofs->z2, proofs->z4, commits->T, e, pedersen_priv->mod.p, 1);
CG21_Pedersen_verify(q_proof, pedersen_priv, proofs->z2, proofs->z4, commits->T, e, pedersen_priv->mod.q, 1);
FF_2048_dmod(p_gt, commits->F, pedersen_priv->mod.p, HFLEN_2048);
FF_2048_dmod(q_gt, commits->F, pedersen_priv->mod.q, HFLEN_2048);
fail = (FF_2048_comp(p_gt, p_proof, HFLEN_2048) != 0) || (FF_2048_comp(q_gt, q_proof, HFLEN_2048) != 0);
if (fail)
{
// ------------ CLEAR MEMORY ----------
FF_2048_zero(p_gt, HFLEN_2048);
FF_2048_zero(q_gt, HFLEN_2048);
FF_2048_zero(p_proof, HFLEN_2048);
FF_2048_zero(q_proof, HFLEN_2048);
return Piaffg_INVALID_PROOF_P2;
}
// ------------ VALIDATES THE PROOF - PART3 ----------
// Split check C^z1 * w^N0 * g^z2 * D^(-e) == A mod N0^2 using CRT
FF_2048_mul(n, verifier_paillier_priv->p, verifier_paillier_priv->q, HFLEN_2048);
FF_2048_fromOctet(CC, C, 2 * FFLEN_2048);
FF_2048_fromOctet(DD, D, 2 * FFLEN_2048);
// Compute check modulo p^2
FF_2048_copy(ws3, verifier_paillier_priv->p2, FFLEN_2048); // ws3 := p^2
FF_2048_zero(ws1, FFLEN_2048);
FF_2048_copy(ws1, verifier_paillier_priv->p, HFLEN_2048); // ws1 := p
FF_2048_sub(ws3, ws3, ws1, FFLEN_2048); // ws3 := p^2 - p
//https://math.stackexchange.com/a/3099042
FF_2048_sub(ws3, ws3, e, FFLEN_2048); // ws3 := p^2 - p - e
FF_2048_norm(ws3, FFLEN_2048);
FF_2048_dmod(ws1, CC, verifier_paillier_priv->p2, FFLEN_2048);
FF_2048_dmod(ws2, DD, verifier_paillier_priv->p2, FFLEN_2048);
// C^z1 * w^N0 * D^-e
FF_2048_ct_pow_3(p_proof, ws1, proofs->z1, proofs->w, n, ws2, ws3, verifier_paillier_priv->p2, FFLEN_2048, FFLEN_2048);
FF_2048_zero(dws, 2 * FFLEN_2048);
FF_2048_mul(dws, n, proofs->z2, FFLEN_2048);
FF_2048_dmod(ws1, dws, verifier_paillier_priv->p2, FFLEN_2048);
FF_2048_inc(ws1, 1, FFLEN_2048);
FF_2048_norm(ws1, FFLEN_2048);
FF_2048_mul(dws, p_proof, ws1, FFLEN_2048);
FF_2048_dmod(p_proof, dws, verifier_paillier_priv->p2, FFLEN_2048);
// Compute check modulo q^2
FF_2048_copy(ws3, verifier_paillier_priv->q2, FFLEN_2048);
FF_2048_zero(ws1, FFLEN_2048);
FF_2048_copy(ws1, verifier_paillier_priv->q, HFLEN_2048);
FF_2048_sub(ws3, ws3, ws1, FFLEN_2048);
FF_2048_sub(ws3, ws3, e, FFLEN_2048);
FF_2048_norm(ws3, FFLEN_2048);
FF_2048_dmod(ws1, CC, verifier_paillier_priv->q2, FFLEN_2048);
FF_2048_dmod(ws2, DD, verifier_paillier_priv->q2, FFLEN_2048);
FF_2048_ct_pow_3(q_proof, ws1, proofs->z1, proofs->w, n, ws2, ws3, verifier_paillier_priv->q2, FFLEN_2048, FFLEN_2048);
FF_2048_mul(dws, n, proofs->z2, FFLEN_2048);
FF_2048_dmod(ws1, dws, verifier_paillier_priv->q2, FFLEN_2048);
FF_2048_inc(ws1, 1, FFLEN_2048);
FF_2048_zero(dws, 2 * FFLEN_2048);
FF_2048_mul(dws, q_proof, ws1, FFLEN_2048);
FF_2048_dmod(q_proof, dws, verifier_paillier_priv->q2, FFLEN_2048);
FF_2048_dmod(p_gt, commits->A, verifier_paillier_priv->p2, FFLEN_2048);
FF_2048_dmod(q_gt, commits->A, verifier_paillier_priv->q2, FFLEN_2048);
fail = (FF_2048_comp(p_gt, p_proof, FFLEN_2048) != 0) || (FF_2048_comp(q_gt, q_proof, FFLEN_2048) != 0);
if (fail)
{
// ------------ CLEAR MEMORY ----------
FF_2048_zero(p_gt, FFLEN_2048);
FF_2048_zero(q_gt, FFLEN_2048);
FF_2048_zero(p_proof, FFLEN_2048);
FF_2048_zero(q_proof, FFLEN_2048);
FF_2048_zero(ws1, FFLEN_2048);
FF_2048_zero(ws2, FFLEN_2048);
FF_2048_zero(ws3, FFLEN_2048);
FF_2048_zero(dws, 2 * FFLEN_2048);
return Piaffg_INVALID_PROOF_P3;
}
// ------------ VALIDATES THE PROOF - PART4 ----------
// z1*G = Bx + e*X
ECP_SECP256K1_generator(&G);
ECP_mul_1024(&G, proofs->z1);
ECP_SECP256K1_copy(&P,&commits->Bx);
ECP_SECP256K1_fromOctet(&Q, X);
ECP_mul_1024(&Q, e);
ECP_SECP256K1_add(&P, &Q);
equal = ECP_SECP256K1_equals(&P, &G);
if (!equal)
{
// ------------ CLEAR MEMORY ----------
FF_2048_zero(p_gt, FFLEN_2048);
FF_2048_zero(q_gt, FFLEN_2048);
FF_2048_zero(p_proof, FFLEN_2048);
FF_2048_zero(q_proof, FFLEN_2048);
FF_2048_zero(ws1, FFLEN_2048);
FF_2048_zero(ws2, FFLEN_2048);
FF_2048_zero(ws3, FFLEN_2048);
FF_2048_zero(dws, 2 * FFLEN_2048);
return Piaffg_INVALID_PROOF_P4;
}
// ------------ VALIDATES THE PROOF - PART5 ----------
// (1+N1)^z2 * wy^N1 = By * Y^e mod N1^2
FF_2048_toOctet(&OCT1, proofs->wy, FFLEN_2048);
OCT_pad(&OCT1, FS_4096);
FF_2048_toOctet(&OCT2, proofs->z2, FFLEN_2048);
OCT_pad(&OCT2, HFS_4096);
OCT_empty(&OCT3);
PAILLIER_ENCRYPT(NULL, prover_paillier_pub, &OCT2, &OCT3,&OCT1);
OCT_pad(X, HFS_4096);
FF_4096_fromOctet(ws4, Y, FFLEN_4096);
OCT_copy(&OCT1, E);
OCT_pad(&OCT1, FS_2048);
FF_4096_fromOctet(ws5, &OCT1, HFLEN_4096);
FF_4096_ct_pow(ws4, ws4, ws5, prover_paillier_pub->n2, FFLEN_4096, HFLEN_4096);
FF_2048_toOctet(&OCT1, commits->By, 2 * FFLEN_2048);
FF_4096_fromOctet(ws6,&OCT1, FFLEN_4096);
FF_4096_zero(dws2, 2 * FFLEN_4096);
FF_4096_mul(dws2, ws4, ws6, FFLEN_4096);
FF_4096_dmod(ws4, dws2, prover_paillier_pub->n2, FFLEN_4096);
FF_4096_fromOctet(ws6,&OCT3, FFLEN_4096);
fail = (FF_4096_comp(ws4, ws6, FFLEN_4096) != 0);
// ------------ CLEAR MEMORY ----------
FF_2048_zero(p_gt, FFLEN_2048);
FF_2048_zero(q_gt, FFLEN_2048);
FF_2048_zero(p_proof, FFLEN_2048);
FF_2048_zero(q_proof, FFLEN_2048);
FF_2048_zero(ws1, FFLEN_2048);
FF_2048_zero(ws2, FFLEN_2048);
FF_2048_zero(ws3, FFLEN_2048);
FF_2048_zero(dws, 2 * FFLEN_2048);
if (fail)
return Piaffg_INVALID_PROOF_P5;
// recall: we already checked 'z1' is in [0, ..., q^3] and 'z2' is in[0, ..., q^7] above
return Piaffg_OK;
}