diff --git a/tpke-wasm/src/lib.rs b/tpke-wasm/src/lib.rs index 10aeb541..31f429b8 100644 --- a/tpke-wasm/src/lib.rs +++ b/tpke-wasm/src/lib.rs @@ -1,4 +1,3 @@ -mod serialization; mod utils; extern crate group_threshold_cryptography as tpke; @@ -31,10 +30,13 @@ pub struct PrivateDecryptionContext { decrypter_index: usize, } -impl PrivateDecryptionContext { - const B_INV_LEN: usize = 32; - const DECRYPTER_INDEX_LEN: usize = 8; +// Keeping this out of the `PrivateDecryptionContext`, since wasm_bindgen doesn't +// support constant field definitions. +const B_INV_LEN: usize = 32; +const DECRYPTER_INDEX_LEN: usize = 8; +#[wasm_bindgen] +impl PrivateDecryptionContext { pub(crate) fn new( b_inv: ark_bls12_381::Fr, decrypter_index: usize, @@ -45,10 +47,11 @@ impl PrivateDecryptionContext { } } - pub fn serialized_size() -> usize { - Self::B_INV_LEN + Self::DECRYPTER_INDEX_LEN + pub(crate) fn serialized_size() -> usize { + B_INV_LEN + DECRYPTER_INDEX_LEN } + #[wasm_bindgen] pub fn to_bytes(&self) -> Vec { let mut bytes = Vec::new(); self.b_inv.0.write(&mut bytes).unwrap(); @@ -60,8 +63,10 @@ impl PrivateDecryptionContext { bytes } + #[wasm_bindgen] pub fn from_bytes(bytes: &[u8]) -> Self { - let b_inv_bytes = &bytes[0..Self::B_INV_LEN]; + let b_inv_bytes = &bytes[0..B_INV_LEN]; + // Chunking bytes to u64s to construct a BigInteger256. let b_inv = b_inv_bytes .chunks(8) .map(|x| { @@ -73,8 +78,8 @@ impl PrivateDecryptionContext { let b_inv: [u64; 4] = b_inv.try_into().unwrap(); let b_inv = ark_bls12_381::Fr::new(BigInteger256::new(b_inv)); - let decrypter_index_bytes = &bytes - [Self::B_INV_LEN..Self::B_INV_LEN + Self::DECRYPTER_INDEX_LEN]; + let decrypter_index_bytes = + &bytes[B_INV_LEN..B_INV_LEN + DECRYPTER_INDEX_LEN]; let decrypter_index = bincode::deserialize(decrypter_index_bytes).unwrap(); @@ -107,10 +112,13 @@ impl DecryptionShare { #[derive(Clone, Debug)] pub struct ParticipantPayload { decryption_context: PrivateDecryptionContext, + // Using inner type here because `ciphertext` is never accessed from the outside. ciphertext: TpkeCiphertext, } +#[wasm_bindgen] impl ParticipantPayload { + #[wasm_bindgen(constructor)] pub fn new( decryption_context: PrivateDecryptionContext, ciphertext: Ciphertext, @@ -121,12 +129,14 @@ impl ParticipantPayload { } } + #[wasm_bindgen] pub fn to_bytes(&self) -> Vec { let mut bytes = self.decryption_context.to_bytes(); bytes.extend(&self.ciphertext.to_bytes()); bytes } + #[wasm_bindgen] pub fn from_bytes(bytes: &[u8]) -> Self { let decryption_context_bytes = &bytes[0..PrivateDecryptionContext::serialized_size()]; @@ -143,9 +153,9 @@ impl ParticipantPayload { } } + #[wasm_bindgen] pub fn to_decryption_share(&self) -> DecryptionShare { // TODO: Add verification steps - let decryption_share = self .ciphertext .nonce @@ -163,16 +173,19 @@ impl ParticipantPayload { #[wasm_bindgen] #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct PublicKey( - #[serde_as(as = "serialization::SerdeAs")] pub(crate) TpkePublicKey, + #[serde_as(as = "tpke::serialization::SerdeAs")] pub(crate) TpkePublicKey, ); +#[wasm_bindgen] impl PublicKey { + #[wasm_bindgen] pub fn from_bytes(bytes: &[u8]) -> Self { let mut reader = bytes; let pk = TpkePublicKey::deserialize_uncompressed(&mut reader).unwrap(); PublicKey(pk) } + #[wasm_bindgen] pub fn to_bytes(&self) -> Vec { let mut bytes = Vec::new(); self.0.serialize_uncompressed(&mut bytes).unwrap(); @@ -183,16 +196,19 @@ impl PublicKey { #[wasm_bindgen] #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct PrivateKey( - #[serde_as(as = "serialization::SerdeAs")] pub(crate) TpkePrivateKey, + #[serde_as(as = "tpke::serialization::SerdeAs")] pub(crate) TpkePrivateKey, ); +#[wasm_bindgen] impl PrivateKey { + #[wasm_bindgen] pub fn from_bytes(bytes: &[u8]) -> Self { let mut reader = bytes; let pk = TpkePrivateKey::deserialize_uncompressed(&mut reader).unwrap(); PrivateKey(pk) } + #[wasm_bindgen] pub fn to_bytes(&self) -> Vec { let mut bytes = Vec::new(); self.0.serialize_uncompressed(&mut bytes).unwrap(); @@ -239,6 +255,7 @@ impl Setup { // as a workaround for wasm-bindgen not supporting `Vec` with a custom defined types without serde // serialization. + #[wasm_bindgen] pub fn private_context_at(&self, index: usize) -> PrivateDecryptionContext { set_panic_hook(); let context = self.private_contexts[index].clone(); @@ -246,6 +263,7 @@ impl Setup { context } + #[wasm_bindgen] pub fn decrypter_indexes(&self) -> Vec { set_panic_hook(); self.private_contexts @@ -284,6 +302,7 @@ pub struct SharedSecretBuilder { shares: Vec, contexts: Vec, } + #[wasm_bindgen] impl SharedSecretBuilder { #[wasm_bindgen(constructor)] diff --git a/tpke-wasm/src/serialization.rs b/tpke-wasm/src/serialization.rs deleted file mode 100644 index 4d31db92..00000000 --- a/tpke-wasm/src/serialization.rs +++ /dev/null @@ -1,86 +0,0 @@ -//! This adds a few utility functions for serializing and deserializing -//! [arkworks](http://arkworks.rs/) types that implement [CanonicalSerialize] and [CanonicalDeserialize]. -//! Adapted from [o1-labs/proof-systems](https://raw.githubusercontent.com/o1-labs/proof-systems/31c76ceae3122f0ce09cded8260960ed5cbbe3d8/utils/src/serialization.rs). - -use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; -use serde_with::Bytes; - -// -// Serialization with serde -// - -#[allow(dead_code)] -pub mod ser { - //! You can use this module for serialization and deserializing arkworks types with [serde]. - //! Simply use the following attribute on your field: - //! `#[serde(with = "serialization::ser") attribute"]` - - use super::*; - use serde_with::{DeserializeAs, SerializeAs}; - - /// You can use this to serialize an arkworks type with serde and the "serialize_with" attribute. - /// See - pub fn serialize( - val: impl CanonicalSerialize, - serializer: S, - ) -> Result - where - S: serde::Serializer, - { - let mut bytes = vec![]; - val.serialize(&mut bytes) - .map_err(serde::ser::Error::custom)?; - - Bytes::serialize_as(&bytes, serializer) - } - - /// You can use this to deserialize an arkworks type with serde and the "deserialize_with" attribute. - /// See - pub fn deserialize<'de, T, D>(deserializer: D) -> Result - where - T: CanonicalDeserialize, - D: serde::Deserializer<'de>, - { - let bytes: Vec = Bytes::deserialize_as(deserializer)?; - T::deserialize(&mut &bytes[..]).map_err(serde::de::Error::custom) - } -} - -// -// Serialization with [serde_with] -// - -/// You can use [SerdeAs] with [serde_with] in order to serialize and deserialize types that implement [CanonicalSerialize] and [CanonicalDeserialize], -/// or containers of types that implement these traits (Vec, arrays, etc.) -/// Simply add annotations like `#[serde_as(as = "serialization::SerdeAs")]` -/// See -pub struct SerdeAs; - -impl serde_with::SerializeAs for SerdeAs -where - T: CanonicalSerialize, -{ - fn serialize_as(val: &T, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut bytes = vec![]; - val.serialize(&mut bytes) - .map_err(serde::ser::Error::custom)?; - - Bytes::serialize_as(&bytes, serializer) - } -} - -impl<'de, T> serde_with::DeserializeAs<'de, T> for SerdeAs -where - T: CanonicalDeserialize, -{ - fn deserialize_as(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let bytes: Vec = Bytes::deserialize_as(deserializer)?; - T::deserialize(&mut &bytes[..]).map_err(serde::de::Error::custom) - } -} diff --git a/tpke/src/decryption.rs b/tpke/src/decryption.rs index 424e5ff2..1857fd46 100644 --- a/tpke/src/decryption.rs +++ b/tpke/src/decryption.rs @@ -20,13 +20,18 @@ impl DecryptionShare { bytes.extend(&decrypter_index); CanonicalSerialize::serialize(&self.decryption_share, &mut bytes) .unwrap(); + bytes } pub fn from_bytes(bytes: &[u8]) -> Self { - let decrypter_index = bincode::deserialize(&bytes[0..8]).unwrap(); + let INDEX_BYTE_LEN = 8; + let decrypter_index = + bincode::deserialize(&bytes[0..INDEX_BYTE_LEN]).unwrap(); let decryption_share = - CanonicalDeserialize::deserialize(&bytes[8..]).unwrap(); + CanonicalDeserialize::deserialize(&bytes[INDEX_BYTE_LEN..]) + .unwrap(); + DecryptionShare { decrypter_index, decryption_share, diff --git a/tpke/src/lib.rs b/tpke/src/lib.rs index f2ff26bb..7ecd37c7 100644 --- a/tpke/src/lib.rs +++ b/tpke/src/lib.rs @@ -15,7 +15,6 @@ use thiserror::Error; mod ciphertext; mod hash_to_curve; -mod serialization; pub use ciphertext::*; mod key_share; pub use key_share::*; @@ -25,6 +24,8 @@ mod combine; pub use combine::*; mod context; pub use context::*; +// TODO: Turn into a crate feature +pub mod serialization; pub trait ThresholdEncryptionParameters { type E: PairingEngine;