in src/cg21/cg21_rp_pi_logstar.c [374:507]
int PiLogstar_Verify(PAILLIER_public_key *pub_key, PEDERSEN_PRIV *priv_com, octet *C_oct, octet *g,
PiLogstar_COMMITS *commits, octet *X, octet *e_oct, PiLogstar_PROOFS *proofs)
{
int fail;
int equal;
ECP_SECP256K1 G;
ECP_SECP256K1 P;
ECP_SECP256K1 Q;
// ------------ VARIABLE DEFINITION ----------
BIG_1024_58 ws[FFLEN_2048];
BIG_1024_58 hws1[HFLEN_2048];
BIG_1024_58 hws2[HFLEN_2048];
BIG_1024_58 wp_proof[HFLEN_2048];
BIG_1024_58 wq_proof[HFLEN_2048];
BIG_1024_58 e[HFLEN_2048];
BIG_512_60 e_4096[HFLEN_4096];
BIG_512_60 s1[HFLEN_4096];
BIG_512_60 ws1_4096[FFLEN_4096];
BIG_512_60 ws2_4096[FFLEN_4096];
BIG_512_60 dws_4096[2 * FFLEN_4096];
char oct[FS_2048];
octet OCT = {0, sizeof(oct), oct};
// ------------ READ INPUTS ----------
OCT_copy(&OCT, e_oct);
OCT_pad(&OCT, HFS_2048);
FF_2048_fromOctet(e, &OCT, HFLEN_2048);
OCT_pad(&OCT, HFS_4096);
FF_4096_fromOctet(e_4096, &OCT, HFLEN_4096);
OCT_clear(&OCT);
// Read q and compute q^3
CG21_GET_CURVE_ORDER(hws1); // hws1 is now q
FF_2048_sqr(ws, hws1, HFLEN_2048); // ws is q^2
FF_2048_mul(ws, ws, hws1, HFLEN_2048); // ws is now q^3
// ------------ CHECK 'z1' IS IN [0, ..., q^3] ------------
if (FF_2048_comp(proofs->z1, ws, FFLEN_2048) > 0)
{
return PiLogstar_INVALID_RANGE;
}
// ------------ VALIDATES THE PROOF - PART1 ----------
// s^z1 * t^z3 =? D * S^e
// Split computation of proofs for C using CRT.
CG21_Pedersen_verify(wp_proof, priv_com, proofs->z1, proofs->z3, commits->S, e, priv_com->mod.p,false);
CG21_Pedersen_verify(wq_proof, priv_com, proofs->z1, proofs->z3, commits->S, e, priv_com->mod.q, false);
// Reduce C mod P and Q for comparison
FF_2048_dmod(hws1, commits->D, priv_com->mod.p, HFLEN_2048);
FF_2048_dmod(hws2, commits->D, priv_com->mod.q, HFLEN_2048);
// Compare the results modulo P and Q
// since C == C' mod PQ <==> C == C' mod P & C == C' mod Q
fail = (FF_2048_comp(hws1, wp_proof, HFLEN_2048) != 0) || (FF_2048_comp(hws2, wq_proof, HFLEN_2048) != 0);
// ------------ CLEAN MEMORY ----------
FF_2048_zero(hws1, HFLEN_2048);
FF_2048_zero(hws2, HFLEN_2048);
FF_2048_zero(wp_proof, HFLEN_2048);
FF_2048_zero(wq_proof, HFLEN_2048);
if(fail)
{
return PiLogstar_INVALID_PROOF_P1;
}
// ------------ VALIDATES THE PROOF - PART2 ----------
//(1+N)^z1 * z2^N * C_oct^(-e) mod N^2 =? A
FF_2048_toOctet(&OCT, proofs->z1, HFLEN_2048);
OCT_pad(&OCT, HFS_4096);
FF_4096_fromOctet(s1, &OCT, HFLEN_4096);
FF_4096_fromOctet(ws1_4096, C_oct, FFLEN_4096);
FF_4096_invmodp(ws1_4096, ws1_4096, pub_key->n2, FFLEN_4096);
// u_proof = (1+N)^z1 * z2^N * C_oct^(-e) mod N^2 , (u_proof = ws2_4096 * ws1_4096)
FF_4096_mul(ws2_4096, pub_key->n, s1, HFLEN_4096);
FF_4096_inc(ws2_4096, 1, FFLEN_4096);
FF_4096_norm(ws2_4096, FFLEN_4096);
FF_4096_nt_pow_2(ws1_4096, proofs->z2, pub_key->n, ws1_4096, e_4096, pub_key->n2, FFLEN_4096, HFLEN_4096);
FF_4096_mul(dws_4096, ws1_4096, ws2_4096, FFLEN_4096);
FF_4096_dmod(ws1_4096, dws_4096, pub_key->n2, FFLEN_4096);
// ------------ CLEAN MEMORY ----------
OCT_clear(&OCT);
FF_4096_zero(dws_4096, 2 * FFLEN_4096);
FF_4096_zero(ws2_4096, FFLEN_4096);
FF_4096_zero(s1, HFLEN_4096);
// ------------ OUTPUT ----------
if(FF_4096_comp(ws1_4096, commits->A, FFLEN_4096) != 0)
{
FF_4096_zero(ws1_4096, FFLEN_4096);
return PiLogstar_INVALID_PROOF_P2;
}
// ------------ VALIDATES THE PROOF - PART4 ----------
// z1*G =? Y + e*X
int rc = ECP_SECP256K1_fromOctet(&G, g);
if (rc != 1)
{
return Pilogstar_Y_FAIL;
}
ECP_mul_1024(&G, proofs->z1);
ECP_SECP256K1_copy(&P,&commits->Y); // P <- Y
ECP_SECP256K1_fromOctet(&Q, X); // Q <- X
ECP_mul_1024(&Q, e); // Q <- e * X
ECP_SECP256K1_add(&P, &Q); // P <- Y + e * X
equal = ECP_SECP256K1_equals(&P, &G);
// ------------ CLEAN MEMORY ----------
ECP_SECP256K1_inf(&G);
ECP_SECP256K1_inf(&P);
ECP_SECP256K1_inf(&Q);
FF_4096_zero(ws1_4096, FFLEN_4096);
if (equal!=1)
{
return PiLogstar_INVALID_PROOF_P3;
}
// Note that 'z1' is already checked to be in the range of [0, ..., q^3]
return PiLogstar_OK;
}