diff --git a/src/key.rs b/src/key.rs index 95df77e..8c47fdc 100644 --- a/src/key.rs +++ b/src/key.rs @@ -4,6 +4,9 @@ use ff::{PrimeField, PrimeFieldBits}; use group::Curve; use rand_core::{CryptoRng, RngCore}; +#[cfg(feature = "multicore")] +use rayon::prelude::*; + #[cfg(feature = "pairing")] use bls12_381::{hash_to_curve::HashToField, G1Affine, G1Projective, Scalar}; #[cfg(feature = "pairing")] @@ -359,3 +362,21 @@ mod tests { assert!(PublicKey::from_bytes(&[255u8; 48]).is_err()); } } + +pub fn aggregate_public_keys(public_keys: &[PublicKey]) -> Result { + + if public_keys.is_empty() { + return Err(Error::ZeroSizedInput); + } + + let res = public_keys + .into_par_iter() + .fold(G1Projective::identity, |mut acc, public_key| { + acc += &public_key.0; + acc + }) + .reduce(G1Projective::identity, |acc, val| acc + val); + + Ok(PublicKey(res.into())) +} + diff --git a/src/lib.rs b/src/lib.rs index 0c9d09b..421d6d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,7 @@ mod signature; pub use self::error::Error; pub use self::key::{PrivateKey, PublicKey, Serialize}; -pub use self::signature::{aggregate, hash, verify, verify_messages, Signature}; +pub use self::signature::{aggregate, hash, verify, verify_messages, verify_agg_signatures_on_same_hash, Signature}; #[cfg(test)] #[macro_use] diff --git a/src/signature.rs b/src/signature.rs index f5ffb64..490cbf4 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -179,6 +179,14 @@ pub fn verify(signature: &Signature, hashes: &[G2Projective], public_keys: &[Pub ml.final_exponentiation() == Gt::identity() } +pub fn verify_agg_signatures_on_same_hash(signature: &Signature, hash: &G2Projective, public_keys: &[PublicKey]) -> bool { + // Aggregate the public keys into a single public key + let pub_key_aggregated = aggregate_public_keys(public_keys).unwrap(); + + // Verify this as normal + verify(signature, std::slice::from_ref(hash), std::slice::from_ref(&pub_key_aggregated)) +} + /// Verifies that the signature is the actual aggregated signature of messages - pubkeys. /// Calculated by `e(g1, signature) == \prod_{i = 0}^n e(pk_i, hash_i)`. #[cfg(feature = "pairing")]