use core::borrow::Borrow;
use alloc::collections::BTreeMap;
use ark_ec::AffineRepr;
use ark_ff::field_hashers::{DefaultFieldHasher, HashToField};
use ark_serialize::CanonicalSerialize;
use digest::FixedOutputReset;
use ark_ec::CurveGroup;
use alloc::vec;
use alloc::vec::Vec;
use super::*;
pub type PublicKeyProjective<E> = <E as EngineBLS>::PublicKeyGroup;
pub type PublicKeyAffine<E> = <<E as EngineBLS>::PublicKeyGroup as CurveGroup>::Affine;
pub type SignatureProjective<E> = <E as EngineBLS>::SignatureGroup;
pub type SignatureAffine<E> = <<E as EngineBLS>::SignatureGroup as CurveGroup>::Affine;
fn verify_normalized<E: EngineBLS>(
affine_publickeys: &[PublicKeyAffine<E>],
affine_messages: &[SignatureAffine<E>],
affine_signature: SignatureAffine<E>,
) -> bool {
let prepared_sig = E::prepare_signature(affine_signature);
let prepared = affine_publickeys
.iter()
.zip(affine_messages)
.map(|(pk, m)| (E::prepare_public_key(*pk), E::prepare_signature(*m)))
.collect::<Vec<_>>();
E::verify_prepared(prepared_sig, prepared.iter())
}
fn collect_messages_and_publickeys<S: Signed>(
s: S,
) -> (
SignatureProjective<S::E>,
Vec<PublicKeyProjective<S::E>>,
Vec<SignatureProjective<S::E>>,
) {
let signature = s.signature().0;
let itr = s.messages_and_publickeys();
let l = {
let (lower, upper) = itr.size_hint();
upper.unwrap_or(lower)
};
let mut publickeys = Vec::with_capacity(l);
let mut messages = Vec::with_capacity(l);
for (message, publickey) in itr {
publickeys.push(publickey.borrow().0);
messages.push(message.borrow().hash_to_signature_curve::<S::E>());
}
(signature, publickeys, messages)
}
fn merge_by_signer<E: EngineBLS>(
affine_publickeys: Vec<PublicKeyAffine<E>>,
messages: Vec<SignatureProjective<E>>,
) -> (Vec<PublicKeyAffine<E>>, Vec<SignatureProjective<E>>) {
type PkMsg<E> = (PublicKeyAffine<E>, SignatureProjective<E>);
let mut pks_n_ms: BTreeMap<Vec<u8>, PkMsg<E>> = BTreeMap::new();
for (pk, m) in affine_publickeys.into_iter().zip(messages) {
let mut pk_bytes = vec![0; pk.uncompressed_size()];
pk.serialize_uncompressed(&mut pk_bytes[..]).unwrap();
pks_n_ms
.entry(pk_bytes)
.and_modify(|(_, m0)| *m0 += m)
.or_insert((pk, m));
}
pks_n_ms.into_values().unzip()
}
fn normalize_publickeys<E: EngineBLS>(
publickeys: &[PublicKeyProjective<E>],
batch_normalize: bool,
) -> Vec<PublicKeyAffine<E>> {
if batch_normalize {
E::PublicKeyGroup::normalize_batch(publickeys)
} else {
publickeys.iter().map(|pk| pk.into_affine()).collect()
}
}
fn normalize_messages_and_signature<E: EngineBLS>(
mut messages: Vec<SignatureProjective<E>>,
signature: SignatureProjective<E>,
) -> (Vec<SignatureAffine<E>>, SignatureAffine<E>) {
messages.push(signature);
let mut affine = E::SignatureGroup::normalize_batch(&messages);
let signature = affine.pop().unwrap();
(affine, signature)
}
pub fn verify_unoptimized<S: Signed>(s: S) -> bool {
let signature = S::E::prepare_signature(s.signature().0);
let prepared = s
.messages_and_publickeys()
.map(|(message, public_key)| {
(
S::E::prepare_public_key(public_key.borrow().0),
S::E::prepare_signature(message.borrow().hash_to_signature_curve::<S::E>()),
)
})
.collect::<Vec<(_, _)>>();
S::E::verify_prepared(signature, prepared.iter())
}
pub fn verify_simple<S: Signed>(s: S) -> bool {
let (signature, publickeys, messages) = collect_messages_and_publickeys(s);
let affine_pks = PublicKeyProjective::<S::E>::normalize_batch(&publickeys);
let (affine_msgs, affine_sig) =
normalize_messages_and_signature::<S::E>(messages, signature);
verify_normalized::<S::E>(&affine_pks, &affine_msgs, affine_sig)
}
pub fn verify_with_distinct_messages<S: Signed>(signed: S, normalize_public_keys: bool) -> bool {
let (signature, publickeys, messages) = collect_messages_and_publickeys(signed);
let affine_publickeys = normalize_publickeys::<S::E>(&publickeys, normalize_public_keys);
let (merged_pks, merged_msgs) = merge_by_signer::<S::E>(affine_publickeys, messages);
let (affine_msgs, affine_sig) =
normalize_messages_and_signature::<S::E>(merged_msgs, signature);
verify_normalized::<S::E>(&merged_pks, &affine_msgs, affine_sig)
}
pub fn verify_using_aggregated_auxiliary_public_keys<
E: EngineBLS,
H: FixedOutputReset + Default + Clone,
>(
signed: &single_pop_aggregator::SignatureAggregatorAssumingPoP<E>,
normalize_public_keys: bool,
aggregated_aux_pub_key: <E as EngineBLS>::SignatureGroup,
) -> bool {
let signature = Signed::signature(&signed).0;
let mut signature_as_bytes = vec![0; signature.compressed_size()];
signature
.serialize_compressed(&mut signature_as_bytes[..])
.expect("compressed size has been alocated");
let itr = signed.messages_and_publickeys();
let l = {
let (lower, upper) = itr.size_hint();
upper.unwrap_or(lower)
};
let (first_message, first_public_key) = match signed.messages_and_publickeys().next() {
Some((first_message, first_public_key)) => (first_message, first_public_key),
None => return false,
};
let mut first_public_key_as_bytes = vec![0; first_public_key.compressed_size()];
first_public_key
.serialize_compressed(&mut first_public_key_as_bytes[..])
.expect("compressed size has been alocated");
let first_message_point = first_message.hash_to_signature_curve::<E>();
let first_message_point_as_bytes = E::signature_point_to_byte(&first_message_point);
let mut aggregated_aux_pub_key_as_bytes = vec![0; aggregated_aux_pub_key.compressed_size()];
aggregated_aux_pub_key
.serialize_compressed(&mut aggregated_aux_pub_key_as_bytes[..])
.expect("compressed size has been alocated");
let pseudo_random_scalar_seed = [
first_message_point_as_bytes,
first_public_key_as_bytes,
aggregated_aux_pub_key_as_bytes,
signature_as_bytes,
]
.concat();
let hasher = <DefaultFieldHasher<H> as HashToField<E::Scalar>>::new(&[]);
let pseudo_random_scalar: E::Scalar =
hasher.hash_to_field::<1>(&pseudo_random_scalar_seed[..])[0];
let signature = signature + aggregated_aux_pub_key * pseudo_random_scalar;
let mut publickeys = Vec::with_capacity(l);
let mut messages = Vec::with_capacity(l);
for (m, pk) in itr {
publickeys.push(pk.0);
messages.push(
m.hash_to_signature_curve::<E>()
+ E::SignatureGroupAffine::generator() * pseudo_random_scalar,
);
}
let affine_publickeys = normalize_publickeys::<E>(&publickeys, normalize_public_keys);
let (merged_pks, merged_msgs) = merge_by_signer::<E>(affine_publickeys, messages);
let (affine_msgs, affine_sig) =
normalize_messages_and_signature::<E>(merged_msgs, signature);
verify_normalized::<E>(&merged_pks, &affine_msgs, affine_sig)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{Keypair, Message, UsualBLS};
use ark_bls12_381::Bls12_381;
use rand::rngs::StdRng;
use rand::SeedableRng;
type EB = UsualBLS<Bls12_381, ark_bls12_381::Config>;
#[test]
fn verify_simple_single_signature() {
let good = Message::new(b"ctx", b"test message");
let mut keypair = Keypair::<EB>::generate(StdRng::from_seed([0u8; 32]));
let signed = keypair.signed_message(&good);
assert!(verify_simple(&signed));
}
#[test]
fn verify_simple_rejects_wrong_message() {
let good = Message::new(b"ctx", b"test message");
let bad = Message::new(b"ctx", b"wrong message");
let mut keypair = Keypair::<EB>::generate(StdRng::from_seed([0u8; 32]));
let sig = keypair.sign(&good);
let wrong_signed = single::SignedMessage {
message: bad,
publickey: keypair.public,
signature: sig,
};
assert!(!verify_simple(&wrong_signed));
}
#[test]
fn verify_unoptimized_single_signature() {
let good = Message::new(b"ctx", b"test message");
let mut keypair = Keypair::<EB>::generate(StdRng::from_seed([0u8; 32]));
let signed = keypair.signed_message(&good);
assert!(verify_unoptimized(&signed));
}
}