int CG21_PRESIGN_ROUND2()

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