in src/cg21/cg21_presign.c [210:391]
int CG21_PRESIGN_ROUND2(csprng *RNG, CG21_PRESIGN_ROUND2_OUTPUT *r2output, CG21_PRESIGN_ROUND2_STORE *r2store,
const CG21_PRESIGN_ROUND1_OUTPUT *r1output, const CG21_PRESIGN_ROUND1_STORE *r1store,
PAILLIER_public_key *hisPK, PAILLIER_public_key *myPK){
r2store->i = r1store->i;
r2output->i = r1store->i;
r2store->j = r1output->i;
r2output->j = r1output->i;
/*
* ---------STEP 1: compute Gamma = gamma*G -----------
*/
BIG_256_56 s;
ECP_SECP256K1 G;
ECP_SECP256K1_generator(&G); // get curve generator
BIG_256_56_fromBytesLen(s, r1store->gamma->val, r1store->gamma->len); // load gamma into big
ECP_SECP256K1_mul(&G, s); // compute gamma*G
ECP_SECP256K1_toOctet(r2store->Gamma, &G, true); // store gamma*G
ECP_SECP256K1_toOctet(r2output->Gamma, &G, true); // store gamma*G
BIG_256_56_zero(s); // zeroize s
/*
* ---------STEP 2: choosing randoms (CG21: Fig.7, Round 2) -----------
* beta: q^5 bits
* beta_hat: q^5 bits
*/
BIG_1024_58 q[HFLEN_2048]; //curve order
BIG_1024_58 q2[FFLEN_2048]; //q^2
BIG_1024_58 q3[FFLEN_2048]; //q^3
BIG_1024_58 q5[FFLEN_2048]; //q^5
BIG_1024_58 t[FFLEN_2048];
char oct1[2 * FS_2048];
octet OCT = {0, sizeof(oct1), oct1};
// Curve order
CG21_get_q(&OCT); // get curve order
OCT_pad(&OCT, HFS_2048); // pad curve order with zeros to become 1024-bit number
FF_2048_fromOctet(q, &OCT, HFLEN_2048); // store padded curve order in q
FF_2048_sqr(q2, q, HFLEN_2048);
FF_2048_mul(q3, q, q2, HFLEN_2048);
FF_2048_mul(q5, q3, q2, FFLEN_2048);
// Generate beta in [0, .., q^5]
FF_2048_random(t, RNG, FFLEN_2048); //t: a 2048-bit
FF_2048_mod(t, q5, FFLEN_2048); //t mod q^5
FF_2048_toOctet(r2store->beta,t, FFLEN_2048);
// Generate beta_hat in [0, .., q^5]
FF_2048_random(t, RNG, FFLEN_2048); //t: a 2048-bit
FF_2048_mod(t, q5, FFLEN_2048); //t mod q^5
FF_2048_toOctet(r2store->beta_hat,t, FFLEN_2048);
FF_2048_zero(t, FFLEN_2048);
/*
* ---------STEP 3: choosing randoms -----------
* r: Z^*_N
* r_hat: Z^*_N
* s: Z^*_N
* s_hat: Z^*_N
*/
// sample rho and nu
BIG_512_60 rr[FFLEN_4096];
BIG_512_60 rr_hat[FFLEN_4096];
BIG_512_60 ss[FFLEN_4096];
BIG_512_60 ss_hat[FFLEN_4096];
FF_4096_zero(rr,FFLEN_4096);
FF_4096_zero(rr_hat,FFLEN_4096);
FF_4096_zero(ss,FFLEN_4096);
FF_4096_zero(ss_hat,FFLEN_4096);
FF_4096_randomnum(rr, myPK->n, RNG,HFLEN_4096);
FF_4096_randomnum(rr_hat, myPK->n, RNG,HFLEN_4096);
FF_4096_randomnum(ss, hisPK->n, RNG,HFLEN_4096);
FF_4096_randomnum(ss_hat, hisPK->n, RNG,HFLEN_4096);
FF_4096_toOctet(r2store->r,rr,FFLEN_4096);
FF_4096_toOctet(r2store->r_hat,rr_hat,FFLEN_4096);
FF_4096_toOctet(r2store->s,ss,FFLEN_4096);
FF_4096_toOctet(r2store->s_hat,ss_hat,FFLEN_4096);
FF_4096_zero(rr,FFLEN_4096);
FF_4096_zero(rr_hat,FFLEN_4096);
FF_4096_zero(ss,FFLEN_4096);
FF_4096_zero(ss_hat,FFLEN_4096);
/*
* ---------STEP 4: compute F and F_hat -----------
* F: Enc(Beta, r)
* F_hat: Enc(Beta_hat, r_hat)
*/
PAILLIER_ENCRYPT(NULL, myPK, r2store->beta, r2output->F, r2store->r);
PAILLIER_ENCRYPT(NULL, myPK, r2store->beta_hat, r2output->F_hat, r2store->r_hat);
/*
* ---------STEP 5: compute H and H_hat -----------
* H: Enc(-Beta, s)
* H_hat: Enc(-Beta_hat, s_hat)
*/
BIG_1024_58 t_[FFLEN_2048];
char H[FS_4096];
octet H_oct = {0, sizeof(H), H};
char H_hat[FS_4096];
octet H_hat_oct = {0, sizeof(H_hat), H_hat};
char ct[FS_4096];
octet CT = {0, sizeof(ct), ct};
// store -Beta
OCT_pad(r2store->neg_beta, HFS_4096);
FF_2048_fromOctet(t, r2store->beta,FFLEN_2048);
FF_2048_sub(t_, q5, t,FFLEN_2048); // t_ = -beta mod q5
FF_2048_norm(t_, FFLEN_2048);
FF_2048_toOctet(r2store->neg_beta,t_, FFLEN_2048);
// Enc(Beta, s)
PAILLIER_ENCRYPT(NULL, hisPK, r2store->beta, &H_oct, r2store->s);
// store -Beta_hat
OCT_pad(r2store->neg_beta_hat, HFS_4096);
FF_2048_fromOctet(t, r2store->beta_hat,FFLEN_2048);
FF_2048_sub(t_, q5, t,FFLEN_2048); // -beta_hat mod q5
FF_2048_norm(t_, FFLEN_2048);
FF_2048_toOctet(r2store->neg_beta_hat,t_, FFLEN_2048);
// Enc(Beta_hat, s_hat)
PAILLIER_ENCRYPT(NULL, hisPK, r2store->beta_hat, &H_hat_oct, r2store->s_hat);
FF_2048_zero(t, FFLEN_2048);
FF_2048_zero(t_, FFLEN_2048);
/*
* ---------STEP 6: compute D and D_hat -----------
* D: K*gamma + H
* D_hat: K*a + H_hat ('a' is the additive share computed in Round1)
*/
char oct11[FS_2048];
char oct22[FS_2048];
octet OCT1 = {0, sizeof(oct11), oct11};
octet OCT2 = {0, sizeof(oct22), oct22};
OCT_copy(&OCT1, r1store->gamma);
OCT_copy(&OCT2, r1store->a);
// PAILLIER_MULT takes plaintext as BIG_512_60 pt[HFLEN_4096], so we should pad our PTs
OCT_pad(&OCT1, HFS_4096);
OCT_pad(&OCT2, HFS_4096);
// CT = E_A(K.gamma)
PAILLIER_MULT(hisPK, r1output->K, &OCT1, &CT);
// D = E_A(K.gamma + H)
PAILLIER_ADD(hisPK, &CT, &H_oct, r2output->D);
// CT = E_A(K.a)
PAILLIER_MULT(hisPK, r1output->K, &OCT2, &CT);
// D_hat = E_A(K.a + H_hat)
PAILLIER_ADD(hisPK, &CT, &H_hat_oct, r2output->D_hat);
OCT_clear(&OCT1);
OCT_clear(&OCT2);
OCT_clear(&H_hat_oct);
OCT_clear(&CT);
return CG21_OK;
}