int PiAffp_Verify()

in src/cg21/cg21_rp_pi_affp.c [499:776]


int PiAffp_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,
                  PiAffp_COMMITS *commits, octet *E, PiAffp_PROOFS *proofs){

    // ------------ VARIABLE DEFINITION ---------
    int fail;

    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);

    FF_2048_sqr(q2, q, HFLEN_2048);             // q^2
    FF_2048_mul(q3, q, q2, HFLEN_2048);      // q^3
    FF_2048_mul(q5, q3, q2, FFLEN_2048);     // q^5
    FF_2048_mul(q7, q5, q2, FFLEN_2048);     // q^7

    // ------------ 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 PiAffp_INVALID_RANGE;
    }

    // load a 256-bit challenge octet e into 2048-bit big e
    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 PiAffp_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 PiAffp_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);     // n = p * q

    FF_2048_fromOctet(CC, C, 2 * FFLEN_2048);
    FF_2048_fromOctet(DD, D, 2 * FFLEN_2048);

    // CRT: 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);  // ws1 = C mod p^2
    FF_2048_dmod(ws2, DD, verifier_paillier_priv->p2, FFLEN_2048);  // ws2 = D mod p^2

    // p_proof := C^z1 * w^N0 * D^-e modulo p^2 = (C mod p^2)^e * w^N0 * (D mod p^2)^{p^2 - p - e} mod p^2
    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_mul(dws, n, proofs->z2, FFLEN_2048);                        // dws := n * z2
    FF_2048_dmod(ws1, dws, verifier_paillier_priv->p2, FFLEN_2048);     // ws1 := (n * z2) mod p^2
    FF_2048_inc(ws1, 1, FFLEN_2048);                                      // ws1 := (n * z2) mod p^2 + 1
    FF_2048_norm(ws1, FFLEN_2048);

    // dws := ((n * z2) mod p^2 + 1) * p_proof
    FF_2048_mul(dws, p_proof, ws1, FFLEN_2048);
    FF_2048_dmod(p_proof, dws, verifier_paillier_priv->p2, FFLEN_2048); // dws := dws mod p^2

    // CRT: 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);

    // // C^z1 * w^N0 * D^-e modulo q^2
    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_zero(dws, 2 * 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);     // p_gt := A mod p^2
    FF_2048_dmod(q_gt, commits->A, verifier_paillier_priv->q2, FFLEN_2048);     // q_gt := A mod q^2

    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 PiAffp_INVALID_PROOF_P3;
    }

    // ------------ VALIDATES THE PROOF - PART4 ----------
    // (1+N1)^z1 * wx^N1 = Bx * X^e mod N1^2

    FF_2048_toOctet(&OCT1, proofs->wx, FFLEN_2048);
    OCT_pad(&OCT1, FS_4096);

    FF_2048_toOctet(&OCT2, proofs->z1, FFLEN_2048);
    OCT_pad(&OCT2, HFS_4096);

    OCT_empty(&OCT3);
    PAILLIER_ENCRYPT(NULL, prover_paillier_pub, &OCT2, &OCT3,&OCT1); // OCT3 := (1+N1)^z1 * wx^N1

    OCT_pad(X, HFS_4096);
    FF_4096_fromOctet(ws4, X, FFLEN_4096);

    OCT_copy(&OCT1, E);
    OCT_pad(&OCT1, FS_2048);
    FF_4096_fromOctet(ws5, &OCT1, HFLEN_4096);

    // ws4 := X^e mod N1^2
    FF_4096_ct_pow(ws4, ws4, ws5, prover_paillier_pub->n2, FFLEN_4096, HFLEN_4096);

    FF_2048_toOctet(&OCT1, commits->Bx, 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); // dws2 := (X^e mod N1^2) * Bx
    FF_4096_dmod(ws4, dws2, prover_paillier_pub->n2, FFLEN_4096); // := (X^e mod N1^2) * Bx mod N1^2

    FF_4096_fromOctet(ws6,&OCT3, FFLEN_4096);
    fail = (FF_4096_comp(ws4, ws6, 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 PiAffp_INVALID_PROOF_P4;
    }

    // ------------ VALIDATES THE PROOF - PART5 ----------
    // Gamma^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); // OCT3 := Gamma^z2 * wy^N1

    OCT_pad(Y, 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);

    // ws4 := Y^e mod N1^2
    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);                        // (Y^e mod N1^2) * By
    FF_4096_dmod(ws4, dws2, prover_paillier_pub->n2, FFLEN_4096);   // (Y^e mod N1^2) * By mod N1^2

    FF_4096_fromOctet(ws6,&OCT3, FFLEN_4096);
    fail = (FF_4096_comp(ws4, ws6, FFLEN_2048) != 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 PiAffp_INVALID_PROOF_P5;

    // recall: we already checked 'z1' is in [0, ..., q^3] and 'z2' is in[0, ..., q^7] above

    return PiAffp_OK;
}