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

Sign

Parties cooperate to sign a message together

Last updated 1 year ago

Signing a message is a procedure which starts from the mobile phone and it is an interactive protocol as key generation protocol. The protocol we are using is from section 3.3 . By the end of the protocol the party who initiated the sign request on a message has the ECDSA signature on the message.

let message = "Hello world!";

// Generate a random session id.
let session_id = SessionId::random();

// Create signer instances for each participant.
let p1signer = P1Signer::new(session_id, keyshare1, message);
let p2signer = P2Signer::new(session_id, keyshare2, message);

// Round 1
let (p1signer, msg1) = p1signer.process(())?;
let (p2signer, msg2) = p2signer.process(msg1)?;

// Round 2
let (p1signer, msg3) = p1signer.process(msg2)?;
let (p2signer, msg4) = p2signer.process(msg3)?;

// Round 3
let msg5 = p1signer.process(msg4)?;
let sign = p2signer.process(msg5)?;

// Distributed signing is complete!

assert!(msg5.sign == sign)
import { P1Signer, P2Signer, generateSessionId } from '@com.silencelaboratories/two-party-ecdsa-js';

// Generate random session id
const session_id = await generateSessionId();

// Get message hash to sign (Using random bytes for example)
const messageHash = randomBytes(32);

// Initialize signer for each party
	/**
	 *   init arguments (same for each signer):
	 * @param session_id  session id
	 * @param keyshare  keyshare
	 * @param messageHash message hash to sign
	 * @param chainPath BIP32 chain path (only soft derivation is supported, e.g. `m/0/1`. Hard derivation like: `m/0'/1` is not supported)
	 * @returns {Promise<P1Signer | P2Signer>}
	 */
const p1Sign = await P1Signer.init(session_id, p1keyshare, messageHash, "m");
const p2Sign = await P2Signer.init(session_id, p2keyshare, messageHash, "m");


// Round 1
const msg1 = await p1Sign.genMsg1();
const signmsg2 = await p2Sign.processMsg1(msg1);

// Round 2
const signmsg3 = await p1Sign.processMsg2(signmsg2);
const sign1 = signmsg3.sign;
const sign2 = await p2Sign.processMsg3(signmsg3);

// Signatures must match
if (sign1 !== sign2) {
    throw new Error("Signatures do not match");
}
tss_buffer sign(Handle *p1_share, Handle *p2_share, tss_buffer *signature, tss_buffer msg_hash) {
    Handle p1_sess;
    Handle p2_sess;

    tss_buffer sess_buf;
    tss_buffer msg1, msg2, msg3, p1_sign, p2_sign;

    tss_buffer derivation_path;
    char m[] = "m";
    derivation_path.ptr = (uint8_t*)m;
    derivation_path.len = strlen(m);

    // 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);

    if (p1_init_signer(&sess_buf, *p1_share, &msg_hash, &derivation_path, &p1_sess) != TSS_OK) {
        perror("Error during p1_signer_gen_msg1\n"); exit(1);
    }

    if (p2_init_signer(&sess_buf, *p2_share, &msg_hash, &derivation_path, &p2_sess) != TSS_OK) {
        perror("Error during p2_signer_gen_msg1\n"); exit(1);
    }

    if (p1_signer_gen_msg1(p1_sess, &msg1) != TSS_OK) {
        perror("Error during p1_signer_gen_msg1\n"); exit(1);
    }

    if (p2_signer_process_msg1(p2_sess, &msg1, &msg2) != TSS_OK) {
        perror("Error during p2_signer_process_msg1\n"); exit(1);
    }

    if (p1_signer_process_msg2(p1_sess, &msg2, &msg3) != TSS_OK) {
        perror("Error during p1_signer_process_msg2\n"); exit(1);
    }

    if (p1_singer_fini(p1_sess, &p1_sign) != TSS_OK) {
        perror("Error during p1_signer_fini\n"); exit(1);
    }

    if (p2_signer_process_msg3(p2_sess, &msg3, &p2_sign) != TSS_OK) {
        perror("Error during p2_signer_fini\n"); exit(1);
    }

    // Check that they have the same signature
    if (p1_sign.len != p2_sign.len) {
        perror("Signatures have different lengths\n"); exit(1);
    }
    for (size_t i = 0; i < p1_sign.len; i++) {
        if (p1_sign.ptr[i] != p2_sign.ptr[i]) {
            perror("Signatures are different\n"); exit(1);
        }
    }

    // Copy the signature to the output
    signature->len = p1_sign.len;
    signature->ptr = malloc(p1_sign.len);
    memcpy((void *)signature->ptr, p1_sign.ptr, p1_sign.len);


    return p2_sign;
}

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