int CG21_PI_MOD_VERIFY()

in src/cg21/cg21_pi_mod.c [379:469]


int CG21_PI_MOD_VERIFY(CG21_PIMOD_PROOF_OCT *paillierProof, const CG21_SSID *ssid, PAILLIER_public_key pk, int n){

    BIG_512_60 r[HFLEN_4096];
    BIG_512_60 num2[HFLEN_4096];
    BIG_512_60 yi_[HFLEN_4096];
    BIG_512_60 yMULw[FFLEN_4096];
    BIG_512_60 n_[FFLEN_4096];

    BIG_1024_58 ws[FFLEN_2048];
    BIG_1024_58 n_2048[FFLEN_2048];
    BIG_1024_58 yi_2048[FFLEN_2048];

    CG21_PIMOD_PROOF pimodProof;

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

    FF_4096_zero(n_,FFLEN_4096);
    FF_4096_copy(n_,pk.n,HFLEN_4096);

    // convert paillier_pk.n from BIG_512_60[HFLEN_4096] to BIG_1024_58[FFLEN_2048]
    FF_4096_toOctet(&OCT, pk.n, HFLEN_4096);
    FF_2048_fromOctet(n_2048, &OCT, FFLEN_2048);

    FF_4096_init(num2,2,HFLEN_4096);
    FF_4096_copy(r,pk.n,HFLEN_4096);

    // r = n % 2
    FF_4096_mod(r, num2,HFLEN_4096);

    // n should be an odd composite number
    if (FF_4096_iszilch(r, HFLEN_4096)){
        return CG21_PAILLIER_N_IS_EVEN;
    }

    int rc = CG21_PI_MOD_proof_fromOCTET(paillierProof, &pimodProof);
    if (rc != CG21_OK){
        return rc;
    }

    // generate yi
    rc = CG21_PI_MOD_CHALLENGE(n_2048, *paillierProof->w, ssid, pimodProof.yi, n);
    if (rc != CG21_OK){
        return rc;
    }

    for (int i=0; i<CG21_PAILLIER_PROOF_ITERS;i++){

        FF_2048_nt_pow(ws, pimodProof.zi[i], n_2048, n_2048, FFLEN_2048, FFLEN_2048);

        // These values are all public, so it is ok to terminate early
        if (FF_2048_comp(ws, pimodProof.yi[i], FFLEN_2048) != 0)
        {
            return CG21_PAILLIER_PROVE_FAIL;
        }
    }

    for (int i=0; i<CG21_PAILLIER_PROOF_ITERS;i++){
        char oct2[2 * FS_2048];
        octet y_oct = {0, sizeof(oct2), oct2};
        FF_2048_toOctet(&y_oct, pimodProof.yi[i], FFLEN_2048);

        FF_4096_zero(yi_, HFLEN_4096);
        FF_4096_fromOctet(yi_, &y_oct, HFLEN_4096);
        // if ai=1 -> (-1)^{ai} becomes -1 -> we compute -yi mod N = N - yi
        // note: if ai=0 -> (-1)^{ai} becomes 0 -> we don't need to do anything
        if (pimodProof.ab[i][0]) {
            FF_4096_sub(yi_, pk.n, yi_, HFLEN_4096);
            FF_4096_norm(yi_, HFLEN_4096);
        }

        // if bi=1 -> we compute yi = w * yi
        if (pimodProof.ab[i][1]) {
            FF_4096_zero(yMULw, FFLEN_4096);
            FF_4096_mul(yMULw, yi_, pimodProof.w, HFLEN_4096);
            FF_4096_mod(yMULw, n_, FFLEN_4096);
            FF_4096_copy(yi_, yMULw, HFLEN_4096);
        }

        FF_4096_toOctet(&OCT, yi_, HFLEN_4096);
        FF_2048_fromOctet(yi_2048, &OCT, FFLEN_2048);
        FF_2048_nt_pow_int(ws,pimodProof.xi[i],4,n_2048,FFLEN_2048);

        if (FF_2048_comp(ws, yi_2048, FFLEN_2048) != 0)
        {
            return CG21_PAILLIER_PROVE_FAIL;
        }
    }

    return CG21_OK;
}