Sign
Parties cooperate to sign a message together
Last updated
Parties cooperate to sign a message together
Last updated
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 https://eprint.iacr.org/2017/552.pdf. 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;
}