Key Generation takes place one time. At the end of that interactive protocol both parties have computed their secret shards which will be used during the signature computation later on. There is no further need to put shards on the network again other than using them during sign phase. The protocol for key generation is described in section 3.2 https://eprint.iacr.org/2017/552.pdf.
Messages between parties are sent within a secure authenticated channel already established between the parties. The messages per se do not expose private information during key generation
In addition, the two parties must agree on who is party 1, and who is party 2 before beginning the key generation steps.
// Generate a random session id.
let session_id = SessionId::random();
// Generate two random secret values for participants.
let x1 = BigInt::sample(256);
let x2 = BigInt::sample(256);
// Create keygen instances for each participant.
let p1 = P1Keygen::new(session_id);
let p2 = P2Keygen::new(session_id);
// Round 1
let (p1, msg1) = p1.process(())?;
let (p2, msg2) = p2.process(msg1)?;
// Round 2
let (keyshare1, msg3) = p1.process(msg2)?;
let keyshare2 = p2.process(msg3)?;
// Distributed key generation is complete. Generated (keyshare1, keyshare2)
assert!(keyshare1.public_key == keyshare2.public_key);
import { P1Keygen, P2Keygen, generateSessionId } from '@com.silencelaboratories/two-party-ecdsa-js';
// Generate random session id
const session_id = await generateSessionId();
// Initialize keygen for each party
const p1Keygen = await P1Keygen.init(session_id);
const p2Keygen = await P2Keygen.init(session_id);
// Round 1
const msg = await p1Keygen.genMsg1();
const msg2 = await p2Keygen.processMsg1(msg);
// Round 2
const [p1keyshare, msg3] = await p1Keygen.processMsg2(msg2);
const p2keyshare = await p2Keygen.processMsg3(msg3);
// p1keyshare and p2keyshare are the secret keyshares of each party
// with same public key
// The create_keyshares function returns the two keyshares that are generated
void create_keyshares(Handle *p1_share, Handle *p2_share, tss_buffer *public_key) {
// Initialize
Handle p1_sess;
Handle p2_sess;
Handle keys = p1_partykeys_new();
tss_buffer sess_buf;
tss_buffer msg1, msg2, msg3, p1_share_buf, p2_share_buf;
// Random Session id generation. Must be 32 bytes.
srand((unsigned int) time(NULL));
uint8_t session_id_data[32];
for (size_t i = 0; i < sizeof(session_id_data); i++) {
session_id_data[i] = rand() % 256;
}
sess_buf.ptr = session_id_data;
sess_buf.len = sizeof(session_id_data);
// P1 keygen init
if (p1_keygen_init(&sess_buf, keys, &p1_sess) != TSS_OK) {
printf("Error during p1_keygen_init\n");
// We hit an error, so panic
perror("Error during p1_keygen_init"); exit(1);
}
// P2 keygen init
if (p2_keygen_init(&sess_buf, &p2_sess) != TSS_OK) {
perror("Error during p2_keygen_init\n"); exit(1);
}
// P1 keygen gen_msg1
if (p1_keygen_gen_msg1(p1_sess, &msg1) != TSS_OK) {
perror("Error during p1_keygen_gen_msg1\n"); exit(1);
}
// P2 keygen process_msg1
if (p2_keygen_process_msg1(p2_sess, &msg1, &msg2) != TSS_OK) {
perror("Error during p2_keygen_process_msg1\n"); exit(1);
}
// P1 keygen process_msg2
if (p1_keygen_process_msg2(p1_sess, &msg2, &msg3) != TSS_OK) {
perror("Error during p1_keygen_process_msg2\n"); exit(1);
}
// P2 keygen process_msg3
if (p2_keygen_process_msg3(p2_sess, &msg3) != TSS_OK) {
perror("Error during p2_keygen_process_msg3\n"); exit(1);
}
// P1 keygen finish
if (p1_keygen_fini(p1_sess, p1_share) != TSS_OK) {
perror("Error during p1_keygen_fini\n"); exit(1);
}
// P1 keyshare public key
if (p1_keyshare_public_key(*p1_share, &p1_share_buf) != TSS_OK) {
perror("Error during p1_keyshare_public_key\n"); exit(1);
}
// P2 keygen finish
if (p2_keygen_fini(p2_sess, p2_share) != TSS_OK) {
perror("Error during p2_keygen_fini\n"); exit(1);
}
// P2 keyshare public key
if (p2_keyshare_public_key(*p2_share, &p2_share_buf) != TSS_OK) {
perror("Error during p2_keyshare_public_key\n"); exit(1);
}
// Verifying keys match
if (p1_share_buf.len != p2_share_buf.len || memcmp(p1_share_buf.ptr, p2_share_buf.ptr, p1_share_buf.len) != 0) {
perror("Public keys do not match\n"); exit(1);
}
// Copying public key to output
public_key->ptr = malloc(p1_share_buf.len);
memcpy((void *)public_key->ptr, (void *)p1_share_buf.ptr, p1_share_buf.len);
public_key->len = p1_share_buf.len;
// Freeing buffers
tss_buffer_free(&msg1);
tss_buffer_free(&msg2);
tss_buffer_free(&msg3);
return;
}