LogoLogo
Duo SDK
  • Introduction
  • Overview
  • Code Stack
  • HOW TO
    • Silent Shard Duo SDK Example
      • Admin
      • Server Node
      • Client Node
        • React-Native
          • Installing Silent Shard Duo RN SDK
          • Quick start
          • Error handling
          • Hooks
            • useECDSAKeyGen
            • useECDSASignGen
            • useECDSAKeyRefresh
          • Functions
            • keyGenECDSA
            • signGenECDSA
            • keyRefreshECDSA
          • Classes
            • ECDSAP1PartyKeys class
            • ECDSAP1KeyshareV2 class
  • ADVANCED SETUP
    • Low Level API
      • Key Generation
      • Sign
      • Key Rotation
    • MPC + Account Abstraction Kits
      • Biconomy Smart Accounts
        • Quick Start
        • Using the CLI version
        • Experience this in a Biconomy x SL powered DApp
      • Stackup Account Abstraction SDK
        • Quick Start
        • Using the CLI version
        • Experience it in a Stackup x SL powered DApp
      • Resources
        • Structure of the repository
        • Integration and Hosting
  • REFERENCE
    • MetaMask Snap
    • Contact Us
Powered by GitBook
On this page
  1. ADVANCED SETUP
  2. Low Level API

Key Generation

Last updated 1 year ago

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 .

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

https://eprint.iacr.org/2017/552.pdf