static void CG21_PI_MOD_GEN_Zi()

in src/cg21/cg21_pi_mod.c [186:266]


static void CG21_PI_MOD_GEN_Zi(CG21_PIMOD_PROOF *pimodProof, CG21_PAILLIER_KEYS paillierKeys){

    BIG_1024_58 Mp[HFLEN_2048];
    BIG_1024_58 Mq[HFLEN_2048];
    BIG_1024_58 Xp[HFLEN_2048];
    BIG_1024_58 Xq[HFLEN_2048];
    BIG_1024_58 ws[FFLEN_2048];
    BIG_1024_58 n_2048[FFLEN_2048];

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

    /* Compute Mp, Mq s.t.
     *
     *   T ← PQ^(-1) mod (P-1)(Q-1)
     *   zi ← yi^T mod PQ, for i ∈ [1 ... m]
     *
     * i.e.
     *   Mp = Q^(-1) mod P-1
     *   Mq = P^(-1) mod Q-1
     */

    // Compute Mp

    // Since P is odd P>>1 = (P-1)/2
    FF_2048_copy(ws, paillierKeys.paillier_sk.p, HFLEN_2048);
    FF_2048_shr(ws, HFLEN_2048);

    // Compute inverse mod (P-1)/2
    FF_2048_invmodp(Mp, paillierKeys.paillier_sk.q, ws, HFLEN_2048);

    // Apply correction to obtain inverse mod P-1
    if (!FF_2048_parity(Mp))
    {
        FF_2048_add(Mp, ws, Mp, HFLEN_2048);
        FF_2048_norm(Mp, HFLEN_2048);
    }

    // Compute Mq

    // Since Q is odd Q>>1 = (Q-1)/2
    FF_2048_copy(ws, paillierKeys.paillier_sk.q, HFLEN_2048);
    FF_2048_shr(ws, HFLEN_2048);

    // Compute inverse mod (Q-1)/2
    FF_2048_invmodp(Mq, paillierKeys.paillier_sk.p, ws, HFLEN_2048);

    // Apply correction to obtain inverse mod Q-1
    if (!FF_2048_parity(Mq))
    {
        FF_2048_add(Mq, ws, Mq, HFLEN_2048);
        FF_2048_norm(Mq, HFLEN_2048);
    }

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

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

        // Xp = yi % p
        FF_2048_dmod(Xp, pimodProof->yi[i], paillierKeys.paillier_sk.p, HFLEN_2048);

        // Xq = yi % q
        FF_2048_dmod(Xq, pimodProof->yi[i], paillierKeys.paillier_sk.q, HFLEN_2048);

        // Compute zi^M using Mp, Mq and CRT
        FF_2048_ct_pow(Xp, Xp, Mp, paillierKeys.paillier_sk.p, HFLEN_2048, HFLEN_2048);
        FF_2048_ct_pow(Xq, Xq, Mq, paillierKeys.paillier_sk.q, HFLEN_2048, HFLEN_2048);

        // zi ← yi^T mod PQ, for i ∈ [1 ... m]
        FF_2048_crt(pimodProof->zi[i], Xp, Xq, paillierKeys.paillier_sk.p, paillierKeys.paillier_sk.invpq, n_2048, HFLEN_2048);
    }

    // clean up
    FF_2048_zero(Mp,HFLEN_2048);
    FF_2048_zero(Mq,HFLEN_2048);
    FF_2048_zero(Xp,HFLEN_2048);
    FF_2048_zero(Xq,FFLEN_2048);
    FF_2048_zero(ws,FFLEN_2048);
}