in src/cg21/cg21_keygen.c [293:364]
int CG21_KEY_GENERATE_ROUND3_2_3(const CG21_KEYGEN_ROUND1_STORE_PRIV *myPriv,
const CG21_KEYGEN_ROUND1_STORE_PUB *pub,
CG21_KEYGEN_ROUND3_STORE *r3,
const CG21_KEYGEN_SID *sid,
CG21_KEYGEN_ROUND3_OUTPUT *r3Output){
BIG_256_56 accum;
BIG_256_56 s;
BIG_256_56 q;
ECP_SECP256K1 G;
char e2[SGS_SECP256K1];
octet E = {0, sizeof(e2), e2};
char o[SFS_SECP256K1 + 1];
octet X = {0, sizeof(o), o};
// Curve order
BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
// Curve generator
ECP_SECP256K1_generator(&G);
char y[myPriv->n-1][EGS_SECP256K1];
octet Y[myPriv->n-1];
init_octets((char *)y, Y, EGS_SECP256K1, myPriv->n-1);
// unpack Y component of the received SSS points
int rc = CG21_unpack(r3->packed_share_Y, myPriv->n-1, Y, EGS_SECP256K1);
if (rc!=CG21_OK){
return rc;
}
int t = myPriv->i - 1;
BIG_256_56_fromBytesLen(accum, (myPriv->shares.Y + t)->val, (myPriv->shares.Y + t)->len);
// compute sum-of-the-shares
for (int i=0; i<myPriv->n-1; i++){
BIG_256_56_fromBytesLen(s, Y[i].val, Y[i].len);
BIG_256_56_add(accum, accum, s);
BIG_256_56_mod(accum, q);
}
// convert sum-of-the-shares to octet
r3->xi.Y->len = EGS_SECP256K1;
BIG_256_56_toBytes(r3->xi.Y->val, accum);
OCT_copy(r3->xi.X,myPriv->shares.X + t);
// computes (sum-of-the-shares)*G
ECP_SECP256K1_mul(&G, accum);
// convert (sum-of-the-shares)*G to octet
ECP_SECP256K1_toOctet(&X, &G, true);
// generate challenge e for Schnorr proof
CG21_GENERATE_CHALLENGE(&X, myPriv->i, *r3->xor_rid, sid, &E);
// Schnorr proof for the knowledge of sum-of-the-shares
SCHNORR_prove(myPriv->tau2, &E, r3->xi.Y, r3Output->xi_proof.psi);
OCT_copy(r3Output->xi_proof.A, pub->A2);
// clean up
BIG_256_56_zero(accum);
BIG_256_56_zero(s);
for (int i=0; i<myPriv->n-1; i++){
OCT_clear(&Y[i]);
}
return CG21_OK;
}