Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a keyshare type for wasm which wraps synedrion::KeyShare #512

Merged
merged 3 commits into from
Nov 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions crypto/protocol/nodejs-test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
70 changes: 59 additions & 11 deletions crypto/protocol/src/user/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u8>,
x25519_private_key_vec: Vec<u8>,
) -> Result<String, Error> {
) -> Result<KeyShare, Error> {
let validators_info = parse_validator_info(validators_info_js)?;

let user_signing_keypair = {
Expand All @@ -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<u8>,
Expand Down Expand Up @@ -80,11 +77,8 @@ pub async fn run_signing_protocol(
x25519_private_key_raw.into()
};

let key_share: KeyShare<KeyParams> =
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,
Expand Down Expand Up @@ -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<KeyParams>);

#[wasm_bindgen]
impl KeyShare {
/// Serialize the keyshare to a JSON string
#[wasm_bindgen(js_name = toString)]
pub fn to_string(&self) -> Result<String, Error> {
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<KeyShare, Error> {
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<Vec<u8>, 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<u8>) -> Result<KeyShare, Error> {
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<u8> {
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()
}
}