From 43e6ededf8882a03fccba60421575415be6da5d3 Mon Sep 17 00:00:00 2001 From: peg Date: Sat, 18 Nov 2023 09:45:49 +0100 Subject: [PATCH] Add a keyshare type for wasm which wraps `synedrion::KeyShare` (#512) * Add a keyshare type for wasm which wraps synedrion::KeyShare * Update nodejs test script * Rm comments --- crypto/protocol/nodejs-test/index.js | 7 +-- crypto/protocol/src/user/wasm.rs | 70 +++++++++++++++++++++++----- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/crypto/protocol/nodejs-test/index.js b/crypto/protocol/nodejs-test/index.js index ec5e48ec6..aa940a867 100644 --- a/crypto/protocol/nodejs-test/index.js +++ b/crypto/protocol/nodejs-test/index.js @@ -33,14 +33,15 @@ try { switch(process.argv[2].toLowerCase()) { case 'register': - protocol.run_dkg_protocol(input.validators_info, input.user_sig_req_seed, input.x25519_private_key).then((output) => { - console.log(output) + protocol.run_dkg_protocol(input.validators_info, input.user_sig_req_seed, input.x25519_private_key).then((keyShare) => { + console.log(keyShare.toString()) }).catch((err) => { console.error('ERR', err) }) break case 'sign': - protocol.run_signing_protocol(input.key_share, input.sig_uid, input.validators_info, input.user_sig_req_seed, input.x25519_private_key).then((output) => { + let keyShare = protocol.KeyShare.fromString(input.key_share) + protocol.run_signing_protocol(keyShare, input.sig_uid, input.validators_info, input.user_sig_req_seed, input.x25519_private_key).then((output) => { console.log(output) }).catch((err) => { console.error('ERR', err) diff --git a/crypto/protocol/src/user/wasm.rs b/crypto/protocol/src/user/wasm.rs index 34e3479b6..8238ffe20 100644 --- a/crypto/protocol/src/user/wasm.rs +++ b/crypto/protocol/src/user/wasm.rs @@ -2,21 +2,19 @@ use js_sys::Error; use subxt::utils::AccountId32; use subxt_signer::sr25519; -use synedrion::KeyShare; use wasm_bindgen::prelude::*; use wasm_bindgen_derive::TryFromJsValue; use super::{user_participates_in_dkg_protocol, user_participates_in_signing_protocol}; use crate::KeyParams; -/// Run the DKG protocol on the client side -/// This returns the keypair as a JSON encoded string +/// Run the DKG protocol on the client side and return a keyshare #[cfg_attr(feature = "wasm", wasm_bindgen)] pub async fn run_dkg_protocol( validators_info_js: ValidatorInfoArray, user_signing_keypair_seed: Vec, x25519_private_key_vec: Vec, -) -> Result { +) -> Result { let validators_info = parse_validator_info(validators_info_js)?; let user_signing_keypair = { @@ -41,15 +39,14 @@ pub async fn run_dkg_protocol( .await .map_err(|err| Error::new(&format!("{}", err)))?; - Ok(serde_json::to_string(&key_share).map_err(|err| Error::new(&err.to_string()))?) + Ok(KeyShare(key_share)) } /// Run the signing protocol on the client side -/// `key_share` is given as a JSON encoded [synedrion::KeyShare] /// Returns a recoverable signature as a base64 encoded string #[cfg_attr(feature = "wasm", wasm_bindgen)] pub async fn run_signing_protocol( - key_share: String, + key_share: KeyShare, sig_uid: String, validators_info_js: ValidatorInfoArray, user_signing_keypair_seed: Vec, @@ -80,11 +77,8 @@ pub async fn run_signing_protocol( x25519_private_key_raw.into() }; - let key_share: KeyShare = - serde_json::from_str(&key_share).map_err(|err| Error::new(&err.to_string()))?; - let signature = user_participates_in_signing_protocol( - &key_share, + &key_share.0, &sig_uid, validators_info, &user_signing_keypair, @@ -177,3 +171,57 @@ fn parse_validator_info( } Ok(validators_info) } + +/// Synedrion key share wrapped for wasm +#[derive(TryFromJsValue)] +#[wasm_bindgen] +#[derive(Clone)] +pub struct KeyShare(synedrion::KeyShare); + +#[wasm_bindgen] +impl KeyShare { + /// Serialize the keyshare to a JSON string + #[wasm_bindgen(js_name = toString)] + pub fn to_string(&self) -> Result { + serde_json::to_string(&self.0).map_err(|err| Error::new(&err.to_string())) + } + + /// Deserialize a keyshare from a JSON string + #[wasm_bindgen(js_name = fromString)] + pub fn from_string(keyshare_json: String) -> Result { + Ok(Self(serde_json::from_str(&keyshare_json).map_err(|err| Error::new(&err.to_string()))?)) + } + + /// Serialize the keyshare to a Uint8Array + #[wasm_bindgen(js_name = toBytes)] + pub fn to_bytes(&self) -> Result, Error> { + bincode::serialize(&self.0).map_err(|err| Error::new(&err.to_string())) + } + + /// Deserialize a keyshare from a Uint8Array + #[wasm_bindgen(js_name = fromBytes)] + pub fn from_bytes(keyshare_serialized: Vec) -> Result { + Ok(Self( + bincode::deserialize(&keyshare_serialized) + .map_err(|err| Error::new(&err.to_string()))?, + )) + } + + /// Get the verifying (public) key associated with this keyshare + #[wasm_bindgen(js_name = verifyingKey)] + pub fn verifying_key(&self) -> Vec { + self.0.verifying_key().to_encoded_point(true).as_bytes().to_vec() + } + + /// Get the number of parties asssociated with this keyshare + #[wasm_bindgen(js_name = numParties)] + pub fn num_parties(&self) -> usize { + self.0.num_parties() + } + + /// Get the party index of this keyshare (a number indentiying which party we are) + #[wasm_bindgen(js_name = partyIndex)] + pub fn party_index(&self) -> usize { + self.0.party_index().as_usize() + } +}