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