int CG21_PI_FACTOR_VERIFY()

in src/cg21/cg21_pi_factor.c [534:751]


int CG21_PI_FACTOR_VERIFY(const CG21_PiFACTOR_COMMIT *r1pub, const CG21_PiFACTOR_PROOF *proof, octet *N_oct,
                          PEDERSEN_PRIV *priv_com, const CG21_SSID *ssid, int n){

    char oct[3*FS_2048];
    octet OCT = {0, sizeof(oct), oct};

    char te[MODBYTES_256_56];
    octet e = {0, sizeof(te), te};

    BIG_1024_58 q[HFLEN_2048];
    BIG_1024_58 q2[FFLEN_2048];
    BIG_1024_58 q3[FFLEN_2048];
    BIG_1024_58 q4[FFLEN_2048];
    BIG_1024_58 q7[FFLEN_2048];

    BIG_1024_58 e_[HFLEN_2048];
    BIG_1024_58 z1[FFLEN_2048 + HFLEN_2048];
    BIG_1024_58 z2[FFLEN_2048 + HFLEN_2048];
    BIG_1024_58 w1[FFLEN_2048 + HFLEN_2048];
    BIG_1024_58 w2[FFLEN_2048 + HFLEN_2048];
    BIG_1024_58 v[2*FFLEN_2048 + HFLEN_2048];
    BIG_1024_58 P[FFLEN_2048];
    BIG_1024_58 Q[FFLEN_2048];
    BIG_1024_58 A[FFLEN_2048];
    BIG_1024_58 B[FFLEN_2048];
    BIG_1024_58 T[FFLEN_2048];

    BIG_1024_58 p_verify[FFLEN_2048];
    BIG_1024_58 q_verify[FFLEN_2048];
    BIG_1024_58 p_gt[FFLEN_2048];
    BIG_1024_58 q_gt[FFLEN_2048];

    BIG_1024_58 t[FFLEN_2048 + HFLEN_2048];
    BIG_1024_58 R[FFLEN_2048];
    BIG_1024_58 t2[2*FFLEN_2048 + HFLEN_2048];
    BIG_1024_58 t3[2*FFLEN_2048 + HFLEN_2048];
    BIG_1024_58 N[FFLEN_2048];

    PEDERSEN_PUB Pedersen_pub;

    FF_2048_fromOctet(N, N_oct, FFLEN_2048);

    // Curve order
    CG21_GET_CURVE_ORDER(q);
    FF_2048_sqr(q2, q, HFLEN_2048);
    FF_2048_mul(q3, q, q2, HFLEN_2048);
    FF_2048_mul(q4, q, q3, HFLEN_2048);
    FF_2048_mul(q7, q4, q3, HFLEN_2048);
    FF_2048_zero(t, FFLEN_2048 + HFLEN_2048);
    FF_2048_copy(t, q7, FFLEN_2048);        // t = q7
    // get Pedersen public parameters
    Pedersen_get_public_param(&Pedersen_pub, priv_com);

    /* Check both z1 and z2 are in the valid range */
    //  load z1
    OCT_clear(&OCT);
    OCT_copy(&OCT, proof->z1);
    OCT_pad(&OCT, FS_2048+ HFS_2048);
    FF_2048_fromOctet(z1, &OCT, FFLEN_2048 + HFLEN_2048);

    // ------------ CHECK 'z1' IS IN [0, ..., t=q^7] ------------
    if (FF_2048_comp(z1, t, FFLEN_2048 + HFLEN_2048) > 0)
    {
        return CG21_PI_FACTOR_INVALID_RANGE;
    }

    //  load z2
    OCT_clear(&OCT);
    OCT_copy(&OCT, proof->z2);
    OCT_pad(&OCT, FS_2048+ HFS_2048);
    FF_2048_fromOctet(z2, &OCT, FFLEN_2048 + HFLEN_2048);

    // ------------ CHECK 'z2' IS IN [0, ..., t=q^7] ------------
    if (FF_2048_comp(z2, t, FFLEN_2048 + HFLEN_2048) > 0)
    {
        return CG21_PI_FACTOR_INVALID_RANGE;
    }

    //  load w1
    OCT_clear(&OCT);
    OCT_copy(&OCT, proof->w1);
    OCT_pad(&OCT, FS_2048 + HFS_2048);
    FF_2048_fromOctet(w1, &OCT, FFLEN_2048 + HFLEN_2048);

    //  load w2
    OCT_clear(&OCT);
    OCT_copy(&OCT, proof->w2);
    OCT_pad(&OCT, FS_2048 + HFS_2048);
    FF_2048_fromOctet(w2, &OCT, FFLEN_2048 + HFLEN_2048);

    //  load v
    OCT_clear(&OCT);
    OCT_copy(&OCT, proof->v);
    OCT_pad(&OCT, 2*FS_2048 + HFS_2048);
    FF_2048_fromOctet(v, &OCT, 2*FFLEN_2048 + HFLEN_2048);

    //  load A
    OCT_clear(&OCT);
    OCT_copy(&OCT, r1pub->A);
    OCT_pad(&OCT, FS_2048);
    FF_2048_fromOctet(A, &OCT, FFLEN_2048);

    //  load B
    OCT_clear(&OCT);
    OCT_copy(&OCT, r1pub->B);
    OCT_pad(&OCT, FS_2048);
    FF_2048_fromOctet(B, &OCT, FFLEN_2048);

    //  load P
    OCT_clear(&OCT);
    OCT_copy(&OCT, r1pub->P);
    OCT_pad(&OCT, FS_2048);
    FF_2048_fromOctet(P, &OCT, FFLEN_2048);

    //  load Q
    OCT_clear(&OCT);
    OCT_copy(&OCT, r1pub->Q);
    OCT_pad(&OCT, FS_2048);
    FF_2048_fromOctet(Q, &OCT, FFLEN_2048);

    //  load T
    OCT_clear(&OCT);
    OCT_copy(&OCT, r1pub->T);
    OCT_pad(&OCT, FS_2048);
    FF_2048_fromOctet(T, &OCT, FFLEN_2048);

    // generate challenge e
    CG21_PI_FACTOR_CHALLENGE(ssid, Pedersen_pub.N, N, &e, n);

    // load octet e as HFLEN_2048 in e_
    OCT_copy(&OCT, &e);
    OCT_pad(&OCT, HFS_2048);
    FF_2048_fromOctet(e_, &OCT, HFLEN_2048);

    /* Split check s^z1 * t^w1 * P^(-e) == A mod PQ using CRT */
    CG21_PI_FACTOR_PED_verify(p_verify, priv_com->b0, priv_com->b1, z1, w1,
                              P, e_, priv_com->mod.p, FFLEN_2048 + HFLEN_2048, FFLEN_2048 + HFLEN_2048);

    CG21_PI_FACTOR_PED_verify(q_verify, priv_com->b0, priv_com->b1, z1, w1,
                              P, e_, priv_com->mod.q, FFLEN_2048 + HFLEN_2048, FFLEN_2048 + HFLEN_2048);


    FF_2048_dmod(p_gt, A, priv_com->mod.p, HFLEN_2048);
    FF_2048_dmod(q_gt, A, priv_com->mod.q, HFLEN_2048);
    int fail = (FF_2048_comp(p_gt, p_verify, HFLEN_2048) != 0) || (FF_2048_comp(q_gt, q_verify, 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_verify, HFLEN_2048);
        FF_2048_zero(q_verify, HFLEN_2048);

        return CG21_PI_FACTOR_INVALID_PROOF;
    }

    /* Split check s^z2 * t^w2 * Q^(-e) == B mod PQ using CRT */
    CG21_PI_FACTOR_PED_verify(p_verify, priv_com->b0, priv_com->b1, z2, w2,
                              Q, e_, priv_com->mod.p, FFLEN_2048 + HFLEN_2048, FFLEN_2048 + HFLEN_2048);

    CG21_PI_FACTOR_PED_verify(q_verify, priv_com->b0, priv_com->b1, z2, w2,
                              Q, e_, priv_com->mod.q, FFLEN_2048 + HFLEN_2048, FFLEN_2048 + HFLEN_2048);

    FF_2048_dmod(p_gt, B, priv_com->mod.p, HFLEN_2048);
    FF_2048_dmod(q_gt, B, priv_com->mod.q, HFLEN_2048);
    fail = (FF_2048_comp(p_gt, p_verify, HFLEN_2048) != 0) || (FF_2048_comp(q_gt, q_verify, 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_verify, HFLEN_2048);
        FF_2048_zero(q_verify, HFLEN_2048);

        return CG21_PI_FACTOR_INVALID_PROOF;
    }

    /* Compute R = s^{pa_N}t^{sigma}*/
    // load sigma
    OCT_clear(&OCT);
    OCT_copy(&OCT, r1pub->sigma);
    OCT_pad(&OCT, 2*FS_2048+HFS_2048);
    FF_2048_fromOctet(t2, &OCT, 2*FFLEN_2048 + HFLEN_2048); // t2 = sigma

    // load Paillier N as 2*FFLEN_2048 + HFLEN_2048
    OCT_clear(&OCT);
    FF_2048_toOctet(&OCT, N, FFLEN_2048);
    OCT_pad(&OCT, 2*FS_2048+HFS_2048);
    FF_2048_fromOctet(t3, &OCT, 2*FFLEN_2048 + HFLEN_2048); // t3 = Paillier N

    // R = s^{pa_N}t^{sigma} mod hat{N}
    FF_2048_ct_pow_2(R, Pedersen_pub.b0, t3, Pedersen_pub.b1, t2,Pedersen_pub.N,
                     FFLEN_2048, 2*FFLEN_2048 + HFLEN_2048);

    /* Q^z1 * t^v * R^(-e) == T mod PQ using CRT */
    CG21_PI_FACTOR_PED_verify(p_verify, Q, priv_com->b1, z1, v,
                              R, e_, priv_com->mod.p, FFLEN_2048 + HFLEN_2048, 2 * FFLEN_2048 + HFLEN_2048);

    CG21_PI_FACTOR_PED_verify(q_verify, Q, priv_com->b1, z1, v,
                              R, e_, priv_com->mod.q, FFLEN_2048 + HFLEN_2048, 2 * FFLEN_2048 + HFLEN_2048);

    FF_2048_dmod(p_gt, T, priv_com->mod.p, HFLEN_2048);
    FF_2048_dmod(q_gt, T, priv_com->mod.q, HFLEN_2048);
    fail = (FF_2048_comp(p_gt, p_verify, HFLEN_2048) != 0) || (FF_2048_comp(q_gt, q_verify, 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_verify, HFLEN_2048);
        FF_2048_zero(q_verify, HFLEN_2048);

        return CG21_PI_FACTOR_INVALID_PROOF;
    }


    return CG21_OK;
}