in src/cg21/cg21_aux.c [203:274]
int CG21_AUX_ROUND3_CHECK_V_N(CG21_SSID *ssid,
CG21_AUX_ROUND1_STORE_PUB round1Pub,
const CG21_AUX_ROUND1_OUT *round1Out){
BIG_512_60 min_n[HFLEN_4096];
hash256 sha;
char v[SHA256];
octet V_r3 = {0, sizeof(v), v};
HASH256_init(&sha);
//Process i into sha
HASH_UTILS_hash_i2osp4(&sha, round1Pub.i);
HASH_UTILS_hash_i2osp4(&sha, sizeof(round1Pub.i));
// process rho and u into sha
HASH_UTILS_hash_oct(&sha, round1Pub.rho);
HASH_UTILS_hash_oct(&sha, round1Pub.u);
// process the curve order and generator into sha
HASH_UTILS_hash_oct(&sha, ssid->g);
HASH_UTILS_hash_oct(&sha, ssid->q);
// process xor-ed rids into sha
HASH_UTILS_hash_oct(&sha, ssid->rid);
// sort partial X[i] based on j_packed and process them into sha
int rc = CG21_hash_set_X(&sha, ssid->X_set_packed, ssid->j_set_packed, round1Pub.t, EFS_SECP256K1 + 1);
if (rc!=CG21_OK){
return rc;
}
HASH_UTILS_hash_oct(&sha, round1Pub.PedPub);
HASH_UTILS_hash_oct(&sha, round1Pub.PaiPub);
HASH_UTILS_hash_oct(&sha, round1Pub.pedersenProof.rho);
HASH_UTILS_hash_oct(&sha, round1Pub.pedersenProof.irho);
HASH_UTILS_hash_oct(&sha, round1Pub.pedersenProof.t);
HASH_UTILS_hash_oct(&sha, round1Pub.pedersenProof.it);
// generates V' from given element from Round2
HASH256_hash(&sha, V_r3.val);
V_r3.len = SHA256;
// compare V' against given V from Round1
int ret = OCT_comp(&V_r3,round1Out->V);
if (ret != 1){
return CG21_AUX_V_IS_NOT_VALID;
}
// compute 2^{8\kappa-1}
FF_4096_init(min_n,1,HFLEN_4096);
FF_4096_norm(min_n,HFLEN_4096);
for (int ii=0; ii<CG21_MINIMUM_N_LENGTH;ii++)
FF_4096_shl(min_n, HFLEN_4096);
// load Paillier public keys
PAILLIER_public_key paillierPub2;
rc = CG21_PaillierPub_from_octet(&paillierPub2, round1Pub.PaiPub);
if (rc!=CG21_OK){
return CG21_UTILITIES_WRONG_PACKED_SIZE;
}
// check Paillier N >= 2^{8\kappa-1}
rc = FF_4096_comp(paillierPub2.n,min_n,HFLEN_4096);
if (rc==-1){
return CG21_PAILLIER_INVALID_N_LENGTH;
}
return CG21_OK;
}