diff --git a/fastcrypto/src/bls12377.rs b/fastcrypto/src/bls12377.rs index 7eab640725..de670a7cdf 100644 --- a/fastcrypto/src/bls12377.rs +++ b/fastcrypto/src/bls12377.rs @@ -35,12 +35,12 @@ use ark_ff::{ One, Zero, }; use celo_bls::{hash_to_curve::try_and_increment, HashToCurve, PublicKey}; -use eyre::eyre; use once_cell::sync::OnceCell; use serde::{de, Deserialize, Serialize}; use serde_with::serde_as; use signature::{Signer, Verifier}; +use crate::error::FastCryptoError; use crate::traits::{Authenticator, KeyPair, SigningKey, VerifyingKey}; use serde_with::{DeserializeAs, SerializeAs}; use zeroize::Zeroize; @@ -362,14 +362,12 @@ impl VerifyingKey for BLS12377PublicKey { msg: &[u8], pks: &[Self], sigs: &[Self::Sig], - ) -> Result<(), eyre::Report> { + ) -> Result<(), FastCryptoError> { if sigs.is_empty() { - return Err(eyre!("Critical Error! This behavious can signal something dangerous, and that someone may be trying to bypass signature verification through providing empty batches.")); + return Err(FastCryptoError::InvalidInput); } if sigs.len() != pks.len() { - return Err(eyre!( - "Mismatch between number of signatures and public keys provided" - )); + return Err(FastCryptoError::InvalidInput); } let mut batch = celo_bls::bls::Batch::new(msg, &[]); pks.iter() @@ -378,7 +376,7 @@ impl VerifyingKey for BLS12377PublicKey { let hash_to_g1 = &*try_and_increment::COMPOSITE_HASH_TO_G1; batch .verify(hash_to_g1) - .map_err(|_| eyre!("Signature verification failed")) + .map_err(|_| FastCryptoError::GeneralError) } } diff --git a/fastcrypto/src/bls12381.rs b/fastcrypto/src/bls12381.rs index 01999f8352..764a52fba7 100644 --- a/fastcrypto/src/bls12381.rs +++ b/fastcrypto/src/bls12381.rs @@ -33,7 +33,7 @@ use crate::{ encoding::Base64, error::FastCryptoError, pubkey_bytes::PublicKeyBytes, serde_helpers::keypair_decode_base64, }; -use eyre::eyre; + use serde::{ de::{self}, Deserialize, Serialize, @@ -56,714 +56,711 @@ use crate::traits::{ // min_pk. macro_rules! define_bls12381 { -( + ( $pk_length:expr, $sig_length:expr, $dst_string:expr ) => { + /// + /// Define Structs + /// + + /// BLS 12-381 public key. + #[readonly::make] + #[derive(Default, Clone)] + pub struct BLS12381PublicKey { + pub pubkey: blst::PublicKey, + pub bytes: OnceCell<[u8; $pk_length]>, + } -/// -/// Define Structs -/// - -/// BLS 12-381 public key. -#[readonly::make] -#[derive(Default, Clone)] -pub struct BLS12381PublicKey { - pub pubkey: blst::PublicKey, - pub bytes: OnceCell<[u8; $pk_length]>, -} - -/// Binary representation of a [BLS12381PublicKey]. -pub type BLS12381PublicKeyBytes = PublicKeyBytes; + /// Binary representation of a [BLS12381PublicKey]. + pub type BLS12381PublicKeyBytes = + PublicKeyBytes; -/// BLS 12-381 private key. -#[readonly::make] -#[derive(SilentDebug, SilentDisplay, Default)] -pub struct BLS12381PrivateKey { - pub privkey: blst::SecretKey, - pub bytes: OnceCell<[u8; BLS_PRIVATE_KEY_LENGTH]>, -} + /// BLS 12-381 private key. + #[readonly::make] + #[derive(SilentDebug, SilentDisplay, Default)] + pub struct BLS12381PrivateKey { + pub privkey: blst::SecretKey, + pub bytes: OnceCell<[u8; BLS_PRIVATE_KEY_LENGTH]>, + } -// There is a strong requirement for this specific impl. in Fab benchmarks. -/// BLS 12-381 public/private keypair. -#[derive(Debug, Serialize, Deserialize)] -#[serde(tag = "type")] // necessary so as not to deserialize under a != type. -pub struct BLS12381KeyPair { - name: BLS12381PublicKey, - secret: BLS12381PrivateKey, -} + // There is a strong requirement for this specific impl. in Fab benchmarks. + /// BLS 12-381 public/private keypair. + #[derive(Debug, Serialize, Deserialize)] + #[serde(tag = "type")] // necessary so as not to deserialize under a != type. + pub struct BLS12381KeyPair { + name: BLS12381PublicKey, + secret: BLS12381PrivateKey, + } -/// BLS 12-381 signature. -#[readonly::make] -#[serde_as] -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct BLS12381Signature { - #[serde_as(as = "BlsSignature")] - pub sig: blst::Signature, - #[serde(skip)] - pub bytes: OnceCell<[u8; $sig_length]>, -} + /// BLS 12-381 signature. + #[readonly::make] + #[serde_as] + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct BLS12381Signature { + #[serde_as(as = "BlsSignature")] + pub sig: blst::Signature, + #[serde(skip)] + pub bytes: OnceCell<[u8; $sig_length]>, + } -/// Aggregation of multiple BLS 12-381 signatures. -#[readonly::make] -#[serde_as] -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct BLS12381AggregateSignature { - #[serde_as(as = "Option")] - pub sig: Option, - #[serde(skip)] - pub bytes: OnceCell<[u8; $sig_length]>, -} + /// Aggregation of multiple BLS 12-381 signatures. + #[readonly::make] + #[serde_as] + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct BLS12381AggregateSignature { + #[serde_as(as = "Option")] + pub sig: Option, + #[serde(skip)] + pub bytes: OnceCell<[u8; $sig_length]>, + } -/// -/// Implement SigningKey -/// + /// + /// Implement SigningKey + /// -impl AsRef<[u8]> for BLS12381PublicKey { - fn as_ref(&self) -> &[u8] { - self.bytes - .get_or_try_init::<_, eyre::Report>(|| Ok(self.pubkey.to_bytes())) - .expect("OnceCell invariant violated") - } -} + impl AsRef<[u8]> for BLS12381PublicKey { + fn as_ref(&self) -> &[u8] { + self.bytes + .get_or_try_init::<_, eyre::Report>(|| Ok(self.pubkey.to_bytes())) + .expect("OnceCell invariant violated") + } + } -impl ToFromBytes for BLS12381PublicKey { - fn from_bytes(bytes: &[u8]) -> Result { - let pubkey = - blst::PublicKey::from_bytes(bytes).map_err(|_| FastCryptoError::InvalidInput)?; - Ok(BLS12381PublicKey { - pubkey, - bytes: OnceCell::new(), - }) - } -} + impl ToFromBytes for BLS12381PublicKey { + fn from_bytes(bytes: &[u8]) -> Result { + let pubkey = blst::PublicKey::from_bytes(bytes) + .map_err(|_| FastCryptoError::InvalidInput)?; + Ok(BLS12381PublicKey { + pubkey, + bytes: OnceCell::new(), + }) + } + } -impl std::hash::Hash for BLS12381PublicKey { - fn hash(&self, state: &mut H) { - self.as_ref().hash(state); - } -} + impl std::hash::Hash for BLS12381PublicKey { + fn hash(&self, state: &mut H) { + self.as_ref().hash(state); + } + } -impl PartialEq for BLS12381PublicKey { - fn eq(&self, other: &Self) -> bool { - self.pubkey == other.pubkey - } -} + impl PartialEq for BLS12381PublicKey { + fn eq(&self, other: &Self) -> bool { + self.pubkey == other.pubkey + } + } -impl Eq for BLS12381PublicKey {} + impl Eq for BLS12381PublicKey {} -impl PartialOrd for BLS12381PublicKey { - fn partial_cmp(&self, other: &Self) -> Option { - self.as_ref().partial_cmp(other.as_ref()) - } -} -impl Ord for BLS12381PublicKey { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.as_ref().cmp(other.as_ref()) - } -} + impl PartialOrd for BLS12381PublicKey { + fn partial_cmp(&self, other: &Self) -> Option { + self.as_ref().partial_cmp(other.as_ref()) + } + } + impl Ord for BLS12381PublicKey { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.as_ref().cmp(other.as_ref()) + } + } -impl Display for BLS12381PublicKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - write!(f, "{}", Base64::encode(self.as_ref())) - } -} + impl Display for BLS12381PublicKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + write!(f, "{}", Base64::encode(self.as_ref())) + } + } -impl Debug for BLS12381PublicKey { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - write!(f, "{}", Base64::encode(self.as_ref())) - } -} + impl Debug for BLS12381PublicKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + write!(f, "{}", Base64::encode(self.as_ref())) + } + } -// There is a strong requirement for this specific impl. in Fab benchmarks. -impl Serialize for BLS12381PublicKey { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_str(&self.encode_base64()) - } -} + // There is a strong requirement for this specific impl. in Fab benchmarks. + impl Serialize for BLS12381PublicKey { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(&self.encode_base64()) + } + } -// There is a strong requirement for this specific impl. in Fab benchmarks. -impl<'de> Deserialize<'de> for BLS12381PublicKey { - fn deserialize(deserializer: D) -> Result - where - D: de::Deserializer<'de>, - { - let s = ::deserialize(deserializer)?; - let value = Self::decode_base64(&s).map_err(|e| de::Error::custom(e.to_string()))?; - Ok(value) - } -} + // There is a strong requirement for this specific impl. in Fab benchmarks. + impl<'de> Deserialize<'de> for BLS12381PublicKey { + fn deserialize(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + let s = ::deserialize(deserializer)?; + let value = + Self::decode_base64(&s).map_err(|e| de::Error::custom(e.to_string()))?; + Ok(value) + } + } -impl Verifier for BLS12381PublicKey { - fn verify(&self, msg: &[u8], signature: &BLS12381Signature) -> Result<(), signature::Error> { - let err = signature - .sig - .verify(true, msg, $dst_string, &[], &self.pubkey, true); - if err == BLST_ERROR::BLST_SUCCESS { - Ok(()) - } else { - Err(signature::Error::new()) + impl Verifier for BLS12381PublicKey { + fn verify( + &self, + msg: &[u8], + signature: &BLS12381Signature, + ) -> Result<(), signature::Error> { + let err = signature + .sig + .verify(true, msg, $dst_string, &[], &self.pubkey, true); + if err == BLST_ERROR::BLST_SUCCESS { + Ok(()) + } else { + Err(signature::Error::new()) + } + } } - } -} -impl<'a> From<&'a BLS12381PrivateKey> for BLS12381PublicKey { - fn from(secret: &'a BLS12381PrivateKey) -> Self { - let inner = &secret.privkey; - let pubkey = inner.sk_to_pk(); - BLS12381PublicKey { - pubkey, - bytes: OnceCell::new(), + impl<'a> From<&'a BLS12381PrivateKey> for BLS12381PublicKey { + fn from(secret: &'a BLS12381PrivateKey) -> Self { + let inner = &secret.privkey; + let pubkey = inner.sk_to_pk(); + BLS12381PublicKey { + pubkey, + bytes: OnceCell::new(), + } + } } - } -} -impl VerifyingKey for BLS12381PublicKey { - type PrivKey = BLS12381PrivateKey; - type Sig = BLS12381Signature; - - const LENGTH: usize = $pk_length; - - fn verify_batch_empty_fail( - msg: &[u8], - pks: &[Self], - sigs: &[Self::Sig], - ) -> Result<(), eyre::Report> { - if sigs.is_empty() { - return Err(eyre!( - "Critical Error! This behaviour can signal something dangerous, and \ - that someone may be trying to bypass signature verification through providing empty \ - batches." - )); - } - if sigs.len() != pks.len() { - return Err(eyre!( - "Mismatch between number of signatures and public keys provided" - )); - } - let aggregated_sig = BLS12381AggregateSignature::aggregate(sigs) - .map_err(|_| eyre!("Signature aggregation before verifying failed!"))?; - aggregated_sig - .verify(pks, msg) - .map_err(|_| eyre!("Batch verification failed!")) - } + impl VerifyingKey for BLS12381PublicKey { + type PrivKey = BLS12381PrivateKey; + type Sig = BLS12381Signature; + + const LENGTH: usize = $pk_length; + + fn verify_batch_empty_fail( + msg: &[u8], + pks: &[Self], + sigs: &[Self::Sig], + ) -> Result<(), FastCryptoError> { + if sigs.is_empty() { + return Err(FastCryptoError::InvalidInput); + } + if sigs.len() != pks.len() { + return Err(FastCryptoError::InvalidInput); + } + let aggregated_sig = BLS12381AggregateSignature::aggregate(sigs) + .map_err(|_| FastCryptoError::GeneralError)?; + aggregated_sig + .verify(pks, msg) + .map_err(|_| FastCryptoError::GeneralError) + } - fn verify_batch_empty_fail_different_msg<'a, M>( - msgs: &[M], - pks: &[Self], - sigs: &[Self::Sig], - ) -> Result<(), eyre::Report> - where - M: Borrow<[u8]> + 'a, - { - if sigs.is_empty() { - return Err(eyre!( - "Critical Error! This behaviour can signal something dangerous, and \ - that someone may be trying to bypass signature verification through providing empty \ - batches." - )); - } - if sigs.len() != pks.len() || msgs.len() != pks.len() { - return Err(eyre!( - "Mismatch between number of messages, signatures and public keys provided" - )); - } - let mut rands: Vec = Vec::with_capacity(sigs.len()); - - // The first coefficient can safely be set to 1 (see https://github.com/MystenLabs/fastcrypto/issues/120) - rands.push(get_one()); - - let mut rng = rand::thread_rng(); - for _ in 1..sigs.len() { - rands.push(get_128bit_scalar(&mut rng)); - } - - let result = blst::Signature::verify_multiple_aggregate_signatures( - &msgs.iter().map(|m| m.borrow()).collect::>(), - $dst_string, - &pks.iter().map(|pk| &pk.pubkey).collect::>(), - false, - &sigs.iter().map(|sig| &sig.sig).collect::>(), - true, - &rands, - 128, - ); - if result == BLST_ERROR::BLST_SUCCESS { - Ok(()) - } else { - Err(eyre!("Batch verification failed!")) + fn verify_batch_empty_fail_different_msg<'a, M>( + msgs: &[M], + pks: &[Self], + sigs: &[Self::Sig], + ) -> Result<(), FastCryptoError> + where + M: Borrow<[u8]> + 'a, + { + if sigs.is_empty() { + return Err(FastCryptoError::InvalidInput); + } + if sigs.len() != pks.len() || msgs.len() != pks.len() { + return Err(FastCryptoError::InvalidInput); + } + let mut rands: Vec = Vec::with_capacity(sigs.len()); + + // The first coefficient can safely be set to 1 (see https://github.com/MystenLabs/fastcrypto/issues/120) + rands.push(get_one()); + + let mut rng = rand::thread_rng(); + for _ in 1..sigs.len() { + rands.push(get_128bit_scalar(&mut rng)); + } + + let result = blst::Signature::verify_multiple_aggregate_signatures( + &msgs.iter().map(|m| m.borrow()).collect::>(), + $dst_string, + &pks.iter().map(|pk| &pk.pubkey).collect::>(), + false, + &sigs.iter().map(|sig| &sig.sig).collect::>(), + true, + &rands, + 128, + ); + if result == BLST_ERROR::BLST_SUCCESS { + Ok(()) + } else { + Err(FastCryptoError::GeneralError) + } + } } - } -} -fn get_128bit_scalar(rng: &mut Rng) -> blst_scalar { - let mut vals = [0u64; 4]; - loop { - vals[0] = rng.next_u64(); - vals[1] = rng.next_u64(); + fn get_128bit_scalar(rng: &mut Rng) -> blst_scalar { + let mut vals = [0u64; 4]; + loop { + vals[0] = rng.next_u64(); + vals[1] = rng.next_u64(); - // Reject zero as it is used for multiplication. - if vals[0] | vals[1] != 0 { - break; + // Reject zero as it is used for multiplication. + if vals[0] | vals[1] != 0 { + break; + } + } + let mut rand_i = MaybeUninit::::uninit(); + unsafe { + blst_scalar_from_uint64(rand_i.as_mut_ptr(), vals.as_ptr()); + return rand_i.assume_init(); + } } - } - let mut rand_i = MaybeUninit::::uninit(); - unsafe { - blst_scalar_from_uint64(rand_i.as_mut_ptr(), vals.as_ptr()); - return rand_i.assume_init(); - } -} -fn get_one() -> blst_scalar { - let mut one = blst_scalar::default(); - let mut vals = [0u8; 32]; - vals[0] = 1; - unsafe { - blst_scalar_from_le_bytes(&mut one, vals.as_ptr(), 32); - } - one -} + fn get_one() -> blst_scalar { + let mut one = blst_scalar::default(); + let mut vals = [0u8; 32]; + vals[0] = 1; + unsafe { + blst_scalar_from_le_bytes(&mut one, vals.as_ptr(), 32); + } + one + } -/// -/// Implement Authenticator -/// + /// + /// Implement Authenticator + /// -impl AsRef<[u8]> for BLS12381Signature { - fn as_ref(&self) -> &[u8] { - self.bytes - .get_or_try_init::<_, eyre::Report>(|| Ok(self.sig.to_bytes())) - .expect("OnceCell invariant violated") - } -} + impl AsRef<[u8]> for BLS12381Signature { + fn as_ref(&self) -> &[u8] { + self.bytes + .get_or_try_init::<_, eyre::Report>(|| Ok(self.sig.to_bytes())) + .expect("OnceCell invariant violated") + } + } -impl std::hash::Hash for BLS12381Signature { - fn hash(&self, state: &mut H) { - self.as_ref().hash(state); - } -} + impl std::hash::Hash for BLS12381Signature { + fn hash(&self, state: &mut H) { + self.as_ref().hash(state); + } + } -impl PartialEq for BLS12381Signature { - fn eq(&self, other: &Self) -> bool { - self.sig == other.sig - } -} + impl PartialEq for BLS12381Signature { + fn eq(&self, other: &Self) -> bool { + self.sig == other.sig + } + } -impl Eq for BLS12381Signature {} + impl Eq for BLS12381Signature {} -impl Signature for BLS12381Signature { - fn from_bytes(bytes: &[u8]) -> Result { - let sig = blst::Signature::from_bytes(bytes).map_err(|_e| signature::Error::new())?; - Ok(BLS12381Signature { - sig, - bytes: OnceCell::new(), - }) - } -} + impl Signature for BLS12381Signature { + fn from_bytes(bytes: &[u8]) -> Result { + let sig = + blst::Signature::from_bytes(bytes).map_err(|_e| signature::Error::new())?; + Ok(BLS12381Signature { + sig, + bytes: OnceCell::new(), + }) + } + } -impl Default for BLS12381Signature { - fn default() -> Self { - // TODO: improve this! - let ikm: [u8; 32] = [ - 0x93, 0xad, 0x7e, 0x65, 0xde, 0xad, 0x05, 0x2a, 0x08, 0x3a, 0x91, 0x0c, 0x8b, 0x72, - 0x85, 0x91, 0x46, 0x4c, 0xca, 0x56, 0x60, 0x5b, 0xb0, 0x56, 0xed, 0xfe, 0x2b, 0x60, - 0xa6, 0x3c, 0x48, 0x99, - ]; + impl Default for BLS12381Signature { + fn default() -> Self { + // TODO: improve this! + let ikm: [u8; 32] = [ + 0x93, 0xad, 0x7e, 0x65, 0xde, 0xad, 0x05, 0x2a, 0x08, 0x3a, 0x91, 0x0c, 0x8b, + 0x72, 0x85, 0x91, 0x46, 0x4c, 0xca, 0x56, 0x60, 0x5b, 0xb0, 0x56, 0xed, 0xfe, + 0x2b, 0x60, 0xa6, 0x3c, 0x48, 0x99, + ]; - let sk = blst::SecretKey::key_gen(&ikm, &[]).unwrap(); + let sk = blst::SecretKey::key_gen(&ikm, &[]).unwrap(); - let msg = b"hello foo"; - let sig = sk.sign(msg, $dst_string, &[]); - BLS12381Signature { - sig, - bytes: OnceCell::new(), + let msg = b"hello foo"; + let sig = sk.sign(msg, $dst_string, &[]); + BLS12381Signature { + sig, + bytes: OnceCell::new(), + } + } } - } -} -impl Display for BLS12381Signature { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - write!(f, "{}", Base64::encode(self.as_ref())) - } -} + impl Display for BLS12381Signature { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + write!(f, "{}", Base64::encode(self.as_ref())) + } + } -impl Authenticator for BLS12381Signature { - type PubKey = BLS12381PublicKey; - type PrivKey = BLS12381PrivateKey; - const LENGTH: usize = $sig_length; -} + impl Authenticator for BLS12381Signature { + type PubKey = BLS12381PublicKey; + type PrivKey = BLS12381PrivateKey; + const LENGTH: usize = $sig_length; + } -/// -/// Implement SigningKey -/// + /// + /// Implement SigningKey + /// -impl AsRef<[u8]> for BLS12381PrivateKey { - fn as_ref(&self) -> &[u8] { - self.bytes - .get_or_try_init::<_, eyre::Report>(|| Ok(self.privkey.to_bytes())) - .expect("OnceCell invariant violated") - } -} + impl AsRef<[u8]> for BLS12381PrivateKey { + fn as_ref(&self) -> &[u8] { + self.bytes + .get_or_try_init::<_, eyre::Report>(|| Ok(self.privkey.to_bytes())) + .expect("OnceCell invariant violated") + } + } -impl ToFromBytes for BLS12381PrivateKey { - fn from_bytes(bytes: &[u8]) -> Result { - let privkey = - blst::SecretKey::from_bytes(bytes).map_err(|_e| FastCryptoError::InvalidInput)?; - Ok(BLS12381PrivateKey { - privkey, - bytes: OnceCell::new(), - }) - } -} + impl ToFromBytes for BLS12381PrivateKey { + fn from_bytes(bytes: &[u8]) -> Result { + let privkey = blst::SecretKey::from_bytes(bytes) + .map_err(|_e| FastCryptoError::InvalidInput)?; + Ok(BLS12381PrivateKey { + privkey, + bytes: OnceCell::new(), + }) + } + } -// There is a strong requirement for this specific impl. in Fab benchmarks -impl Serialize for BLS12381PrivateKey { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_str(&self.encode_base64()) - } -} + // There is a strong requirement for this specific impl. in Fab benchmarks + impl Serialize for BLS12381PrivateKey { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(&self.encode_base64()) + } + } -// There is a strong requirement for this specific impl. in Fab benchmarks -impl<'de> Deserialize<'de> for BLS12381PrivateKey { - fn deserialize(deserializer: D) -> Result - where - D: de::Deserializer<'de>, - { - let s = ::deserialize(deserializer)?; - let value = Self::decode_base64(&s).map_err(|e| de::Error::custom(e.to_string()))?; - Ok(value) - } -} + // There is a strong requirement for this specific impl. in Fab benchmarks + impl<'de> Deserialize<'de> for BLS12381PrivateKey { + fn deserialize(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + let s = ::deserialize(deserializer)?; + let value = + Self::decode_base64(&s).map_err(|e| de::Error::custom(e.to_string()))?; + Ok(value) + } + } -impl SigningKey for BLS12381PrivateKey { - type PubKey = BLS12381PublicKey; - type Sig = BLS12381Signature; - const LENGTH: usize = BLS_PRIVATE_KEY_LENGTH; -} + impl SigningKey for BLS12381PrivateKey { + type PubKey = BLS12381PublicKey; + type Sig = BLS12381Signature; + const LENGTH: usize = BLS_PRIVATE_KEY_LENGTH; + } -impl Signer for BLS12381PrivateKey { - fn try_sign(&self, msg: &[u8]) -> Result { - let sig = self.privkey.sign(msg, $dst_string, &[]); + impl Signer for BLS12381PrivateKey { + fn try_sign(&self, msg: &[u8]) -> Result { + let sig = self.privkey.sign(msg, $dst_string, &[]); - Ok(BLS12381Signature { - sig, - bytes: OnceCell::new(), - }) - } -} + Ok(BLS12381Signature { + sig, + bytes: OnceCell::new(), + }) + } + } -/// -/// Implement KeyPair -/// + /// + /// Implement KeyPair + /// -impl From for BLS12381KeyPair { - fn from(secret: BLS12381PrivateKey) -> Self { - let name = BLS12381PublicKey::from(&secret); - BLS12381KeyPair { name, secret } - } -} + impl From for BLS12381KeyPair { + fn from(secret: BLS12381PrivateKey) -> Self { + let name = BLS12381PublicKey::from(&secret); + BLS12381KeyPair { name, secret } + } + } -impl EncodeDecodeBase64 for BLS12381KeyPair { - fn encode_base64(&self) -> String { - let mut bytes: Vec = Vec::new(); - bytes.extend_from_slice(self.secret.as_ref()); - bytes.extend_from_slice(self.name.as_ref()); - Base64::encode(&bytes[..]) - } + impl EncodeDecodeBase64 for BLS12381KeyPair { + fn encode_base64(&self) -> String { + let mut bytes: Vec = Vec::new(); + bytes.extend_from_slice(self.secret.as_ref()); + bytes.extend_from_slice(self.name.as_ref()); + Base64::encode(&bytes[..]) + } - fn decode_base64(value: &str) -> Result { - keypair_decode_base64(value) - } -} + fn decode_base64(value: &str) -> Result { + keypair_decode_base64(value) + } + } -impl KeyPair for BLS12381KeyPair { - type PubKey = BLS12381PublicKey; - type PrivKey = BLS12381PrivateKey; - type Sig = BLS12381Signature; + impl KeyPair for BLS12381KeyPair { + type PubKey = BLS12381PublicKey; + type PrivKey = BLS12381PrivateKey; + type Sig = BLS12381Signature; - fn public(&'_ self) -> &'_ Self::PubKey { - &self.name - } + fn public(&'_ self) -> &'_ Self::PubKey { + &self.name + } - fn private(self) -> Self::PrivKey { - BLS12381PrivateKey::from_bytes(self.secret.as_ref()).unwrap() - } + fn private(self) -> Self::PrivKey { + BLS12381PrivateKey::from_bytes(self.secret.as_ref()).unwrap() + } - #[cfg(feature = "copy_key")] - fn copy(&self) -> Self { - BLS12381KeyPair { - name: self.name.clone(), - secret: BLS12381PrivateKey::from_bytes(self.secret.as_ref()).unwrap(), - } - } + #[cfg(feature = "copy_key")] + fn copy(&self) -> Self { + BLS12381KeyPair { + name: self.name.clone(), + secret: BLS12381PrivateKey::from_bytes(self.secret.as_ref()).unwrap(), + } + } - fn generate(rng: &mut R) -> Self { - let mut ikm = [0u8; 32]; - rng.fill_bytes(&mut ikm); - let privkey = blst::SecretKey::key_gen(&ikm, &[]).expect("ikm length should be higher"); - let pubkey = privkey.sk_to_pk(); - BLS12381KeyPair { - name: BLS12381PublicKey { - pubkey, - bytes: OnceCell::new(), - }, - secret: BLS12381PrivateKey { - privkey, - bytes: OnceCell::new(), - }, + fn generate(rng: &mut R) -> Self { + let mut ikm = [0u8; 32]; + rng.fill_bytes(&mut ikm); + let privkey = + blst::SecretKey::key_gen(&ikm, &[]).expect("ikm length should be higher"); + let pubkey = privkey.sk_to_pk(); + BLS12381KeyPair { + name: BLS12381PublicKey { + pubkey, + bytes: OnceCell::new(), + }, + secret: BLS12381PrivateKey { + privkey, + bytes: OnceCell::new(), + }, + } + } } - } -} -impl Signer for BLS12381KeyPair { - fn try_sign(&self, msg: &[u8]) -> Result { - let blst_priv: &blst::SecretKey = &self.secret.privkey; - let sig = blst_priv.sign(msg, $dst_string, &[]); + impl Signer for BLS12381KeyPair { + fn try_sign(&self, msg: &[u8]) -> Result { + let blst_priv: &blst::SecretKey = &self.secret.privkey; + let sig = blst_priv.sign(msg, $dst_string, &[]); - Ok(BLS12381Signature { - sig, - bytes: OnceCell::new(), - }) - } -} - -impl FromStr for BLS12381KeyPair { - type Err = eyre::Report; + Ok(BLS12381Signature { + sig, + bytes: OnceCell::new(), + }) + } + } - fn from_str(s: &str) -> Result { - let kp = Self::decode_base64(s).map_err(|e| eyre::eyre!("{}", e.to_string()))?; - Ok(kp) - } -} + impl FromStr for BLS12381KeyPair { + type Err = eyre::Report; -/// -/// Implement AggregateAuthenticator -/// + fn from_str(s: &str) -> Result { + let kp = Self::decode_base64(s).map_err(|e| eyre::eyre!("{}", e.to_string()))?; + Ok(kp) + } + } -// Don't try to use this externally -impl AsRef<[u8]> for BLS12381AggregateSignature { - fn as_ref(&self) -> &[u8] { - match self.sig { - Some(sig) => self - .bytes - .get_or_try_init::<_, eyre::Report>(|| Ok(sig.to_bytes())) - .expect("OnceCell invariant violated"), - None => &[], + /// + /// Implement AggregateAuthenticator + /// + + // Don't try to use this externally + impl AsRef<[u8]> for BLS12381AggregateSignature { + fn as_ref(&self) -> &[u8] { + match self.sig { + Some(sig) => self + .bytes + .get_or_try_init::<_, eyre::Report>(|| Ok(sig.to_bytes())) + .expect("OnceCell invariant violated"), + None => &[], + } + } } - } -} -impl Display for BLS12381AggregateSignature { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - write!(f, "{}", Base64::encode(self.as_ref())) - } -} + impl Display for BLS12381AggregateSignature { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + write!(f, "{}", Base64::encode(self.as_ref())) + } + } -// see [#34](https://github.com/MystenLabs/narwhal/issues/34) -impl Default for BLS12381AggregateSignature { - fn default() -> Self { - BLS12381AggregateSignature { - sig: None, - bytes: OnceCell::new(), + // see [#34](https://github.com/MystenLabs/narwhal/issues/34) + impl Default for BLS12381AggregateSignature { + fn default() -> Self { + BLS12381AggregateSignature { + sig: None, + bytes: OnceCell::new(), + } + } } - } -} -impl AggregateAuthenticator for BLS12381AggregateSignature { - type Sig = BLS12381Signature; - type PubKey = BLS12381PublicKey; - type PrivKey = BLS12381PrivateKey; - - /// Parse a key from its byte representation - fn aggregate<'a, K: Borrow + 'a, I: IntoIterator>( - signatures: I, - ) -> Result { - blst::AggregateSignature::aggregate( - &signatures - .into_iter() - .map(|x| &x.borrow().sig) - .collect::>(), - true, - ) - .map(|sig| BLS12381AggregateSignature { - sig: Some(sig.to_signature()), - bytes: OnceCell::new(), - }) - .map_err(|_| FastCryptoError::GeneralError) - } + impl AggregateAuthenticator for BLS12381AggregateSignature { + type Sig = BLS12381Signature; + type PubKey = BLS12381PublicKey; + type PrivKey = BLS12381PrivateKey; + + /// Parse a key from its byte representation + fn aggregate<'a, K: Borrow + 'a, I: IntoIterator>( + signatures: I, + ) -> Result { + blst::AggregateSignature::aggregate( + &signatures + .into_iter() + .map(|x| &x.borrow().sig) + .collect::>(), + true, + ) + .map(|sig| BLS12381AggregateSignature { + sig: Some(sig.to_signature()), + bytes: OnceCell::new(), + }) + .map_err(|_| FastCryptoError::GeneralError) + } - fn add_signature(&mut self, signature: Self::Sig) -> Result<(), FastCryptoError> { - match self.sig { - Some(ref mut sig) => { - let mut aggr_sig = blst::AggregateSignature::from_signature(sig); - aggr_sig - .add_signature(&signature.sig, true) - .map_err(|_| FastCryptoError::GeneralError)?; - self.sig = Some(aggr_sig.to_signature()); + fn add_signature(&mut self, signature: Self::Sig) -> Result<(), FastCryptoError> { + match self.sig { + Some(ref mut sig) => { + let mut aggr_sig = blst::AggregateSignature::from_signature(sig); + aggr_sig + .add_signature(&signature.sig, true) + .map_err(|_| FastCryptoError::GeneralError)?; + self.sig = Some(aggr_sig.to_signature()); + Ok(()) + } + None => { + self.sig = Some(signature.sig); + Ok(()) + } + } + } + + fn add_aggregate(&mut self, signature: Self) -> Result<(), FastCryptoError> { + match self.sig { + Some(ref mut sig) => match signature.sig { + Some(to_add) => { + let result = blst::AggregateSignature::aggregate(&[sig, &to_add], true) + .map_err(|_| FastCryptoError::GeneralError)? + .to_signature(); + self.sig = Some(result); + Ok(()) + } + None => Ok(()), + }, + None => { + self.sig = signature.sig; + Ok(()) + } + } + } + + fn verify( + &self, + pks: &[::PubKey], + message: &[u8], + ) -> Result<(), FastCryptoError> { + let result = self + .sig + .ok_or(FastCryptoError::GeneralError)? + .fast_aggregate_verify( + true, + message, + $dst_string, + &pks.iter().map(|x| &x.pubkey).collect::>()[..], + ); + if result != BLST_ERROR::BLST_SUCCESS { + return Err(FastCryptoError::GeneralError); + } Ok(()) } - None => { - self.sig = Some(signature.sig); + + fn verify_different_msg( + &self, + pks: &[::PubKey], + messages: &[&[u8]], + ) -> Result<(), FastCryptoError> { + let result = self + .sig + .ok_or(FastCryptoError::GeneralError)? + .aggregate_verify( + true, + messages, + $dst_string, + &pks.iter().map(|x| &x.pubkey).collect::>()[..], + true, + ); + if result != BLST_ERROR::BLST_SUCCESS { + return Err(FastCryptoError::GeneralError); + } Ok(()) } - } - } - fn add_aggregate(&mut self, signature: Self) -> Result<(), FastCryptoError> { - match self.sig { - Some(ref mut sig) => match signature.sig { - Some(to_add) => { - let result = blst::AggregateSignature::aggregate(&[sig, &to_add], true) - .map_err(|_| FastCryptoError::GeneralError)? - .to_signature(); - self.sig = Some(result); - Ok(()) + fn batch_verify<'a>( + signatures: &[&Self], + pks: Vec>, + messages: &[&[u8]], + ) -> Result<(), FastCryptoError> { + if signatures.len() != pks.len() || signatures.len() != messages.len() { + return Err(FastCryptoError::InputLengthWrong(signatures.len())); + } + let mut pk_iter = pks.into_iter(); + for i in 0..signatures.len() { + let sig = signatures[i].sig; + let result = sig + .ok_or(FastCryptoError::GeneralError)? + .fast_aggregate_verify( + true, + messages[i], + $dst_string, + &pk_iter + .next() + .unwrap() + .map(|x| &x.pubkey) + .collect::>()[..], + ); + if result != BLST_ERROR::BLST_SUCCESS { + return Err(FastCryptoError::GeneralError); + } } - None => Ok(()), - }, - None => { - self.sig = signature.sig; Ok(()) } } - } - fn verify( - &self, - pks: &[::PubKey], - message: &[u8], - ) -> Result<(), FastCryptoError> { - let result = self - .sig - .ok_or(FastCryptoError::GeneralError)? - .fast_aggregate_verify( - true, - message, - $dst_string, - &pks.iter().map(|x| &x.pubkey).collect::>()[..], - ); - if result != BLST_ERROR::BLST_SUCCESS { - return Err(FastCryptoError::GeneralError); - } - Ok(()) - } + /// + /// Implement VerifyingKeyBytes + /// - fn verify_different_msg( - &self, - pks: &[::PubKey], - messages: &[&[u8]], - ) -> Result<(), FastCryptoError> { - let result = self - .sig - .ok_or(FastCryptoError::GeneralError)? - .aggregate_verify( - true, - messages, - $dst_string, - &pks.iter().map(|x| &x.pubkey).collect::>()[..], - true, - ); - if result != BLST_ERROR::BLST_SUCCESS { - return Err(FastCryptoError::GeneralError); - } - Ok(()) - } + impl TryFrom for BLS12381PublicKey { + type Error = signature::Error; - fn batch_verify<'a>( - signatures: &[&Self], - pks: Vec>, - messages: &[&[u8]], - ) -> Result<(), FastCryptoError> { - if signatures.len() != pks.len() || signatures.len() != messages.len() { - return Err(FastCryptoError::InputLengthWrong(signatures.len())); - } - let mut pk_iter = pks.into_iter(); - for i in 0..signatures.len() { - let sig = signatures[i].sig; - let result = sig - .ok_or(FastCryptoError::GeneralError)? - .fast_aggregate_verify( - true, - messages[i], - $dst_string, - &pk_iter - .next() - .unwrap() - .map(|x| &x.pubkey) - .collect::>()[..], - ); - if result != BLST_ERROR::BLST_SUCCESS { - return Err(FastCryptoError::GeneralError); + fn try_from(bytes: BLS12381PublicKeyBytes) -> Result { + BLS12381PublicKey::from_bytes(bytes.as_ref()).map_err(|_| Self::Error::new()) } } - Ok(()) - } -} -/// -/// Implement VerifyingKeyBytes -/// - -impl TryFrom for BLS12381PublicKey { - type Error = signature::Error; - - fn try_from(bytes: BLS12381PublicKeyBytes) -> Result { - BLS12381PublicKey::from_bytes(bytes.as_ref()).map_err(|_| Self::Error::new()) - } -} - -impl From<&BLS12381PublicKey> for BLS12381PublicKeyBytes { - fn from(pk: &BLS12381PublicKey) -> BLS12381PublicKeyBytes { - BLS12381PublicKeyBytes::from_bytes(pk.as_ref()).unwrap() - } -} - -impl zeroize::Zeroize for BLS12381PrivateKey { - fn zeroize(&mut self) { - self.bytes.take().zeroize(); - self.privkey.zeroize(); - } -} + impl From<&BLS12381PublicKey> for BLS12381PublicKeyBytes { + fn from(pk: &BLS12381PublicKey) -> BLS12381PublicKeyBytes { + BLS12381PublicKeyBytes::from_bytes(pk.as_ref()).unwrap() + } + } -impl zeroize::ZeroizeOnDrop for BLS12381PrivateKey {} + impl zeroize::Zeroize for BLS12381PrivateKey { + fn zeroize(&mut self) { + self.bytes.take().zeroize(); + self.privkey.zeroize(); + } + } -impl Drop for BLS12381PrivateKey { - fn drop(&mut self) { - self.zeroize(); - } -} + impl zeroize::ZeroizeOnDrop for BLS12381PrivateKey {} -impl zeroize::Zeroize for BLS12381KeyPair { - fn zeroize(&mut self) { - self.secret.zeroize() - } -} + impl Drop for BLS12381PrivateKey { + fn drop(&mut self) { + self.zeroize(); + } + } -impl zeroize::ZeroizeOnDrop for BLS12381KeyPair {} + impl zeroize::Zeroize for BLS12381KeyPair { + fn zeroize(&mut self) { + self.secret.zeroize() + } + } -impl Drop for BLS12381KeyPair { - fn drop(&mut self) { - self.zeroize(); - } -} + impl zeroize::ZeroizeOnDrop for BLS12381KeyPair {} -impl ToFromBytes for BLS12381AggregateSignature { - fn from_bytes(bytes: &[u8]) -> Result { - let sig = blst::Signature::from_bytes(bytes).map_err(|_| FastCryptoError::InvalidInput)?; - Ok(BLS12381AggregateSignature { - sig: Some(sig), - bytes: OnceCell::new(), - }) - } -} + impl Drop for BLS12381KeyPair { + fn drop(&mut self) { + self.zeroize(); + } + } -}} // macro_rules! define_bls12381 + impl ToFromBytes for BLS12381AggregateSignature { + fn from_bytes(bytes: &[u8]) -> Result { + let sig = blst::Signature::from_bytes(bytes) + .map_err(|_| FastCryptoError::InvalidInput)?; + Ok(BLS12381AggregateSignature { + sig: Some(sig), + bytes: OnceCell::new(), + }) + } + } + }; +} // macro_rules! define_bls12381 /// The length of a private key in bytes. pub const BLS_PRIVATE_KEY_LENGTH: usize = 32; diff --git a/fastcrypto/src/ed25519.rs b/fastcrypto/src/ed25519.rs index a709d89b77..2ee3c2a559 100644 --- a/fastcrypto/src/ed25519.rs +++ b/fastcrypto/src/ed25519.rs @@ -16,7 +16,6 @@ use crate::{encoding::Encoding, traits}; use ed25519_consensus::{batch, VerificationKeyBytes}; -use eyre::eyre; use fastcrypto_derive::{SilentDebug, SilentDisplay}; use once_cell::sync::OnceCell; use serde::{ @@ -114,14 +113,12 @@ impl VerifyingKey for Ed25519PublicKey { msg: &[u8], pks: &[Self], sigs: &[Self::Sig], - ) -> Result<(), eyre::Report> { + ) -> Result<(), FastCryptoError> { if sigs.is_empty() { - return Err(eyre!("Critical Error! This behaviour can signal something dangerous, and that someone may be trying to bypass signature verification through providing empty batches.")); + return Err(FastCryptoError::InvalidInput); } if sigs.len() != pks.len() { - return Err(eyre!( - "Mismatch between number of signatures and public keys provided" - )); + return Err(FastCryptoError::InvalidInput); } let mut batch = batch::Verifier::new(); @@ -132,24 +129,22 @@ impl VerifyingKey for Ed25519PublicKey { } batch .verify(OsRng) - .map_err(|_| eyre!("Signature verification failed")) + .map_err(|_| FastCryptoError::GeneralError) } fn verify_batch_empty_fail_different_msg<'a, M>( msgs: &[M], pks: &[Self], sigs: &[Self::Sig], - ) -> Result<(), eyre::Report> + ) -> Result<(), FastCryptoError> where M: Borrow<[u8]> + 'a, { if sigs.is_empty() { - return Err(eyre!("Critical Error! This behaviour can signal something dangerous, and that someone may be trying to bypass signature verification through providing empty batches.")); + return Err(FastCryptoError::InvalidInput); } if pks.len() != sigs.len() || pks.len() != msgs.len() { - return Err(eyre!( - "Mismatch between number of messages, signatures and public keys provided" - )); + return Err(FastCryptoError::InvalidInput); } let mut batch = batch::Verifier::new(); @@ -160,7 +155,7 @@ impl VerifyingKey for Ed25519PublicKey { } batch .verify(OsRng) - .map_err(|_| eyre!("Signature verification failed")) + .map_err(|_| FastCryptoError::GeneralError) } } diff --git a/fastcrypto/src/traits.rs b/fastcrypto/src/traits.rs index a14026ae01..2fb2560b61 100644 --- a/fastcrypto/src/traits.rs +++ b/fastcrypto/src/traits.rs @@ -1,7 +1,6 @@ // Copyright (c) 2021, Facebook, Inc. and its affiliates // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use eyre::eyre; use rand::rngs::{StdRng, ThreadRng}; use rand::{CryptoRng, RngCore}; @@ -119,17 +118,17 @@ pub trait VerifyingKey: /// let signatures = [signature1.clone(), signature2.clone()]; /// assert!(Ed25519PublicKey::verify_batch_empty_fail(message, &public_keys, &signatures).is_ok()); /// ``` - fn verify_batch_empty_fail(msg: &[u8], pks: &[Self], sigs: &[Self::Sig]) -> Result<(), eyre::Report> { + fn verify_batch_empty_fail(msg: &[u8], pks: &[Self], sigs: &[Self::Sig]) -> Result<(), FastCryptoError> { if sigs.is_empty() { - return Err(eyre!("Critical Error! This behaviour can signal something dangerous, and that someone may be trying to bypass signature verification through providing empty batches.")); + return Err(FastCryptoError::InvalidInput); } if pks.len() != sigs.len() { - return Err(eyre!("Mismatch between number of signatures and public keys provided")); + return Err(FastCryptoError::InvalidInput); } pks.iter() .zip(sigs) .try_for_each(|(pk, sig)| pk.verify(msg, sig)) - .map_err(|_| eyre!("Signature verification failed")) + .map_err(|_| FastCryptoError::GeneralError) } // Expected to be overridden by implementations @@ -153,18 +152,18 @@ pub trait VerifyingKey: /// let signatures = [signature1.clone(), signature2.clone()]; /// assert!(Ed25519PublicKey::verify_batch_empty_fail_different_msg(&messages, &public_keys, &signatures).is_ok()); /// ``` - fn verify_batch_empty_fail_different_msg<'a, M>(msgs: &[M], pks: &[Self], sigs: &[Self::Sig]) -> Result<(), eyre::Report> where M: Borrow<[u8]> + 'a { + fn verify_batch_empty_fail_different_msg<'a, M>(msgs: &[M], pks: &[Self], sigs: &[Self::Sig]) -> Result<(), FastCryptoError> where M: Borrow<[u8]> + 'a { if sigs.is_empty() { - return Err(eyre!("Critical Error! This behaviour can signal something dangerous, and that someone may be trying to bypass signature verification through providing empty batches.")); + return Err(FastCryptoError::InvalidInput); } if pks.len() != sigs.len() || pks.len() != msgs.len() { - return Err(eyre!("Mismatch between number of messages, signatures and public keys provided")); + return Err(FastCryptoError::InvalidInput); } pks.iter() .zip(sigs) .zip(msgs) .try_for_each(|((pk, sig), msg)| pk.verify(msg.borrow(), sig)) - .map_err(|_| eyre!("Signature verification failed")) + .map_err(|_| FastCryptoError::GeneralError) } }