in src/cg21/cg21_pi_mod.c [89:184]
static void CG21_PI_MOD_GEN_Xi(CG21_PIMOD_PROOF *pimodProof, CG21_PAILLIER_KEYS paillierKeys){
bool ab_[4][2]={{0,0},{0,1},{1,0},{1,1}};
BIG_512_60 yi_[HFLEN_4096];
BIG_512_60 yMULw[FFLEN_4096];
BIG_512_60 n_[FFLEN_4096];
BIG_1024_58 r1[FFLEN_2048];
BIG_1024_58 r2[FFLEN_2048];
BIG_1024_58 r11[FFLEN_2048];
BIG_1024_58 r22[FFLEN_2048];
BIG_1024_58 yi_2048[FFLEN_2048];
BIG_1024_58 n_2048[FFLEN_2048];
char oct[2*FS_2048];
octet OCT = {0, sizeof(oct), oct};
FF_4096_zero(n_,FFLEN_4096);
FF_4096_copy(n_,paillierKeys.paillier_pk.n,HFLEN_4096);
// 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 each yi[i] we need to choose (ai,bi) from ab_ such that y'i has 4th root
for (int i=0;i<CG21_PAILLIER_PROOF_ITERS;i++){
// convert yi from BIG_1024_58[FFLEN_2048] to y_oct
char oct2[2 * FS_2048];
octet y_oct = {0, sizeof(oct2), oct2};
FF_2048_toOctet(&y_oct, pimodProof->yi[i], FFLEN_2048);
for (int j=0;j<4;j++){
// convert y_oct to BIG_512_60[HFLEN_4096]
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 (ab_[j][0]) {
FF_4096_sub(yi_, paillierKeys.paillier_pk.n, yi_, HFLEN_4096);
FF_4096_norm(yi_, HFLEN_4096);
}
// if bi=1 -> we compute yi = w * yi
if (ab_[j][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);
}
// convert yi_ from BIG_512_60[HFLEN_4096] to BIG_1024_58[FFLEN_2048]
FF_4096_toOctet(&OCT, yi_, HFLEN_4096);
FF_2048_fromOctet(yi_2048, &OCT, FFLEN_2048);
// check whether yi_2048 has any square root in mod p and q
bool rc1 = CG21_check_sqrt_exist(yi_2048, paillierKeys.paillier_sk.p);
bool rc2 = CG21_check_sqrt_exist(yi_2048, paillierKeys.paillier_sk.q);
if (rc1 && rc2){
// 4th root of yi_2048 mod p
CG21_sqrt(r1,yi_2048,paillierKeys.paillier_sk.p);
CG21_sqrt(r11,r1,paillierKeys.paillier_sk.p);
// 4th root of yi_2048 mod q
CG21_sqrt(r2,yi_2048,paillierKeys.paillier_sk.q);
CG21_sqrt(r22,r2,paillierKeys.paillier_sk.q);
// combine r11 and r22 using CRT to get the final result xi
FF_2048_crt(pimodProof->xi[i], r11, r22, paillierKeys.paillier_sk.p, paillierKeys.paillier_sk.invpq, n_2048, HFLEN_2048);
// stores ai and bi values, verifier needs these values
pimodProof->ab[i][0] = ab_[j][0];
pimodProof->ab[i][1] = ab_[j][1];
// don't need to check the other combinations of ai and bi
break;
}
}
}
// clean up
FF_4096_zero(yi_, HFLEN_4096);
FF_4096_zero(yMULw, FFLEN_4096);
FF_4096_zero(n_, FFLEN_4096);
FF_2048_zero(r1, FFLEN_2048);
FF_2048_zero(r2, HFLEN_2048);
FF_2048_zero(r11, FFLEN_2048);
FF_2048_zero(r22, HFLEN_2048);
FF_2048_zero(yi_2048, FFLEN_2048);
FF_2048_zero(n_2048, FFLEN_2048);
OCT_clear(&OCT);
}