diff --git a/plonk/Cargo.toml b/plonk/Cargo.toml index 312457c1e..7081b4539 100644 --- a/plonk/Cargo.toml +++ b/plonk/Cargo.toml @@ -20,7 +20,7 @@ derivative = { version = "2", features = ["use_core"] } displaydoc = { version = "0.2.3", default-features = false } downcast-rs = { version = "1.2.0", default-features = false } dyn-clone = "^1.0" -espresso-systems-common = { git = "https://github.com/espressosystems/espresso-systems-common", branch = "main" } +espresso-systems-common = { git = "https://github.com/espressosystems/espresso-systems-common", tag = "0.4.0" } hashbrown = "0.12.3" itertools = { version = "0.10.1", default-features = false } jf-primitives = { path = "../primitives", default-features = false } diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 25c00a2d7..27677aae5 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -24,7 +24,7 @@ crypto_box = "0.8.1" derivative = { version = "2", features = ["use_core"] } digest = { version = "0.10.1", default-features = false, features = ["alloc"] } displaydoc = { version = "0.2.3", default-features = false } -espresso-systems-common = { git = "https://github.com/espressosystems/espresso-systems-common", branch = "main" } +espresso-systems-common = { git = "https://github.com/espressosystems/espresso-systems-common", tag = "0.4.0" } generic-array = { version = "^0.14", default-features = false } itertools = { version = "0.10.1", default-features = false, features = [ "use_alloc" ] } jf-relation = { path = "../relation", default-features = false } diff --git a/primitives/src/constants.rs b/primitives/src/constants.rs index e017a4be7..0e2f98d20 100644 --- a/primitives/src/constants.rs +++ b/primitives/src/constants.rs @@ -11,3 +11,10 @@ pub const CS_ID_SCHNORR: &str = "SCHNORR_WITH_RESCUE_HASH_v01"; /// ciphersuite identifier for BLS signature pub const CS_ID_BLS_SIG_NAIVE: &str = "BLS_SIG_WITH_NAIVE_HtG_v01"; + +/// Size in bytes of a secret key in our BLS signature scheme. +pub const BLS_SIG_KEY_SIZE: usize = 32; +/// Size in bytes of a signature in our BLS signature scheme. +pub const BLS_SIG_SIGNATURE_SIZE: usize = 96; +/// Size in bytes of a verification key in our BLS signature scheme. +pub const BLS_SIG_VERKEY_SIZE: usize = 192; diff --git a/primitives/src/signatures/bls.rs b/primitives/src/signatures/bls.rs index cb63ac55f..a644f15b9 100644 --- a/primitives/src/signatures/bls.rs +++ b/primitives/src/signatures/bls.rs @@ -1,18 +1,151 @@ //! BLS Signature Scheme use super::SignatureScheme; -use crate::{constants::CS_ID_BLS_SIG_NAIVE, errors::PrimitivesError}; +use crate::{ + constants::{ + BLS_SIG_KEY_SIZE, BLS_SIG_SIGNATURE_SIZE, BLS_SIG_VERKEY_SIZE, CS_ID_BLS_SIG_NAIVE, + }, + errors::PrimitivesError, +}; +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, SerializationError}; use ark_std::{ + convert::TryInto, format, rand::{CryptoRng, RngCore}, }; -use blst::{min_sig::*, BLST_ERROR}; +use blst::BLST_ERROR; +use espresso_systems_common::jellyfish::tag; +use tagged_base64::tagged; -pub use blst::min_sig::{ - PublicKey as BLSVerKey, SecretKey as BLSSignKey, Signature as BLSSignature, -}; +pub use blst::min_sig::{PublicKey, SecretKey, Signature}; +use zeroize::Zeroize; + +/// Newtype wrapper for a BLS Signing Key. +#[tagged(tag::BLS_SIGNING_KEY)] +#[derive(Clone, Debug, Zeroize)] +pub struct BLSSignKey(SecretKey); + +impl core::ops::Deref for BLSSignKey { + type Target = SecretKey; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl CanonicalSerialize for BLSSignKey { + fn serialized_size(&self) -> usize { + BLS_SIG_KEY_SIZE + } + + fn serialize(&self, writer: W) -> Result<(), SerializationError> { + let bytes = &self.0.serialize(); + CanonicalSerialize::serialize(bytes.as_ref(), writer) + } +} + +impl CanonicalDeserialize for BLSSignKey { + fn deserialize(mut reader: R) -> Result { + let len = ::deserialize(&mut reader)?; + if len != BLS_SIG_KEY_SIZE { + return Err(SerializationError::InvalidData); + } + + let mut key = [0u8; BLS_SIG_KEY_SIZE]; + reader.read_exact(&mut key)?; + SecretKey::deserialize(&key) + .map(Self) + .map_err(|_| SerializationError::InvalidData) + } +} + +impl PartialEq for BLSSignKey { + fn eq(&self, other: &Self) -> bool { + self.0.serialize() == other.0.serialize() + } +} + +impl Eq for BLSSignKey {} + +/// Newtype wrapper for a BLS Signature. +#[tagged(tag::BLS_SIG)] +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct BLSSignature(Signature); + +impl core::ops::Deref for BLSSignature { + type Target = Signature; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl CanonicalSerialize for BLSSignature { + fn serialized_size(&self) -> usize { + BLS_SIG_SIGNATURE_SIZE + } + + fn serialize(&self, writer: W) -> Result<(), SerializationError> { + let bytes = &self.0.serialize(); + CanonicalSerialize::serialize(bytes.as_ref(), writer) + } +} + +impl CanonicalDeserialize for BLSSignature { + fn deserialize(mut reader: R) -> Result { + let len = ::deserialize(&mut reader)?; + if len != BLS_SIG_SIGNATURE_SIZE { + return Err(SerializationError::InvalidData); + } + + let mut sig = [0u8; BLS_SIG_SIGNATURE_SIZE]; + reader.read_exact(&mut sig)?; + Signature::deserialize(&sig) + .map(Self) + .map_err(|_| SerializationError::InvalidData) + } +} + +/// Newtype wrapper for a BLS Verification Key. +#[tagged(tag::BLS_VER_KEY)] +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct BLSVerKey(PublicKey); + +impl core::ops::Deref for BLSVerKey { + type Target = PublicKey; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl CanonicalSerialize for BLSVerKey { + fn serialized_size(&self) -> usize { + BLS_SIG_VERKEY_SIZE + } + + fn serialize(&self, writer: W) -> Result<(), SerializationError> { + let bytes = &self.0.serialize(); + CanonicalSerialize::serialize(bytes.as_ref(), writer) + } +} + +impl CanonicalDeserialize for BLSVerKey { + fn deserialize(mut reader: R) -> Result { + let len = ::deserialize(&mut reader)?; + if len != BLS_SIG_VERKEY_SIZE { + return Err(SerializationError::InvalidData); + } + + let mut key = [0u8; BLS_SIG_VERKEY_SIZE]; + reader.read_exact(&mut key)?; + PublicKey::deserialize(&key) + .map(Self) + .map_err(|_| SerializationError::InvalidData) + } +} /// BLS signature scheme. Imports blst library. pub struct BLSSignatureScheme; @@ -55,7 +188,7 @@ impl SignatureScheme for BLSSignatureScheme { Err(e) => return Err(PrimitivesError::InternalError(format!("{:?}", e))), }; let vk = sk.sk_to_pk(); - Ok((sk, vk)) + Ok((BLSSignKey(sk), BLSVerKey(vk))) } /// Sign a message @@ -65,7 +198,11 @@ impl SignatureScheme for BLSSignatureScheme { msg: M, _prng: &mut R, ) -> Result { - Ok(sk.sign(msg.as_ref(), Self::CS_ID.as_bytes(), &[])) + Ok(BLSSignature(sk.sign( + msg.as_ref(), + Self::CS_ID.as_bytes(), + &[], + ))) } /// Verify a signature. @@ -84,6 +221,8 @@ impl SignatureScheme for BLSSignatureScheme { #[cfg(test)] mod test { + use ark_std::{test_rng, vec::Vec}; + use super::*; use crate::signatures::tests::{failed_verification, sign_and_verify}; @@ -94,4 +233,29 @@ mod test { sign_and_verify::(message.as_ref()); failed_verification::(message.as_ref(), message_bad.as_ref()); } + + #[test] + fn test_bls_sig_serde() { + let rng = &mut test_rng(); + let parameters = BLSSignatureScheme::param_gen(Some(rng)).unwrap(); + let (sk, vk) = BLSSignatureScheme::key_gen(¶meters, rng).unwrap(); + + // serde for Verification Key + let mut keypair_bytes = Vec::new(); + vk.serialize(&mut keypair_bytes).unwrap(); + let keypair_de = BLSVerKey::deserialize(&keypair_bytes[..]).unwrap(); + assert_eq!(vk, keypair_de); + // wrong byte length + assert!(BLSVerKey::deserialize(&keypair_bytes[1..]).is_err()); + + // serde for Signature + let message = "this is a test message"; + let sig = BLSSignatureScheme::sign(¶meters, &sk, message.as_bytes(), rng).unwrap(); + let mut sig_bytes = Vec::new(); + sig.serialize(&mut sig_bytes).unwrap(); + let sig_de = BLSSignature::deserialize(&sig_bytes[..]).unwrap(); + assert_eq!(sig, sig_de); + // wrong byte length + assert!(BLSSignature::deserialize(&sig_bytes[1..]).is_err()); + } } diff --git a/primitives/src/signatures/mod.rs b/primitives/src/signatures/mod.rs index 9f72e5304..a9cf8c6b3 100644 --- a/primitives/src/signatures/mod.rs +++ b/primitives/src/signatures/mod.rs @@ -6,8 +6,10 @@ use ark_std::rand::{CryptoRng, RngCore}; pub mod bls; pub mod schnorr; pub use bls::BLSSignatureScheme; +use core::fmt::Debug; pub use schnorr::SchnorrSignatureScheme; - +use serde::{Deserialize, Serialize}; +use zeroize::Zeroize; /// Trait definition for a signature scheme. // A signature scheme is associated with a hash function H that is // to be used for challenge generation. @@ -17,19 +19,41 @@ pub trait SignatureScheme { const CS_ID: &'static str; /// Signing key. - type SigningKey; + type SigningKey: Debug + + Clone + + Send + + Sync + + Zeroize + + for<'a> Deserialize<'a> + + Serialize + + PartialEq + + Eq; /// Verification key - type VerificationKey; + type VerificationKey: Debug + + Clone + + Send + + Sync + + for<'a> Deserialize<'a> + + Serialize + + PartialEq + + Eq; /// Public Parameter type PublicParameter; /// Signature - type Signature; + type Signature: Debug + + Clone + + Send + + Sync + + for<'a> Deserialize<'a> + + Serialize + + PartialEq + + Eq; /// A message is &\[MessageUnit\] - type MessageUnit; + type MessageUnit: Debug + Clone + Send + Sync; /// generate public parameters from RNG. /// If the RNG is not presented, use the default group generator. diff --git a/primitives/src/signatures/schnorr.rs b/primitives/src/signatures/schnorr.rs index c726031f4..368eef9e9 100644 --- a/primitives/src/signatures/schnorr.rs +++ b/primitives/src/signatures/schnorr.rs @@ -102,6 +102,7 @@ where // ===================================================== // Signing key // ===================================================== +#[tagged(tag::SCHNORR_SIGNING_KEY)] #[derive( Clone, Hash, Default, Zeroize, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize, Debug, )] @@ -127,7 +128,7 @@ impl SignKey { /// Signature public verification key // derive zeroize here so that keypair can be zeroized -#[tagged(tag::SCHNORRVERKEY)] +#[tagged(tag::SCHNORR_VER_KEY)] #[derive(CanonicalSerialize, CanonicalDeserialize, Derivative)] #[derivative( Debug(bound = "P: Parameters"), @@ -196,7 +197,7 @@ impl VerKey

{ /// Signature secret key pair used to sign messages // make sure sk can be zeroized -#[tagged(tag::SIGNKEYPAIR)] +#[tagged(tag::SCHNORR_KEY_PAIR)] #[derive(CanonicalSerialize, CanonicalDeserialize, Derivative)] #[derivative( Debug(bound = "P: Parameters"), @@ -217,7 +218,7 @@ where // ===================================================== /// The signature of Schnorr signature scheme -#[tagged(tag::SIG)] +#[tagged(tag::SCHNORR_SIG)] #[derive(CanonicalSerialize, CanonicalDeserialize, Derivative)] #[derivative( Debug(bound = "P: Parameters"), diff --git a/utilities/src/serialize.rs b/utilities/src/serialize.rs index e7d43d36c..5f5e0b7f7 100644 --- a/utilities/src/serialize.rs +++ b/utilities/src/serialize.rs @@ -9,9 +9,9 @@ use ark_std::vec::Vec; use serde::{Deserialize, Serialize}; -/// A helper for converting CanonicalSerde bytes to standard Serde bytes. -/// use this struct as intermediate target instead of directly deriving -/// serde::Serialize/Deserialize to avoid implementation of Visitors. +/// A helper for converting ark_serialize::CanonicalSerialize bytes to standard +/// Serde bytes. Use this struct as intermediate target instead of directly +/// deriving serde::Serialize/Deserialize to avoid implementation of Visitors. #[derive(Serialize, Deserialize)] pub struct CanonicalBytes(pub Vec);