use crate::{
error::BBSPlusError,
setup::{PreparedPublicKeyG2, PreparedSignatureParams23G1, SecretKey, SignatureParams23G1},
};
use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup, Group};
use ark_ff::{fields::Field, PrimeField};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::{
collections::BTreeMap, fmt::Debug, ops::Mul, rand::RngCore, vec::Vec, UniformRand, Zero,
};
use dock_crypto_utils::{expect_equality, serde_utils::*, signature::MultiMessageSignatureParams};
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use zeroize::{Zeroize, ZeroizeOnDrop};
#[serde_as]
#[derive(
Clone,
Debug,
PartialEq,
Eq,
CanonicalSerialize,
CanonicalDeserialize,
Serialize,
Deserialize,
Zeroize,
ZeroizeOnDrop,
)]
pub struct Signature23G1<E: Pairing> {
#[serde_as(as = "ArkObjectBytes")]
pub A: E::G1Affine,
#[serde_as(as = "ArkObjectBytes")]
pub e: E::ScalarField,
}
impl<E: Pairing> Signature23G1<E> {
pub fn new<R: RngCore>(
rng: &mut R,
messages: &[E::ScalarField],
sk: &SecretKey<E::ScalarField>,
params: &SignatureParams23G1<E>,
) -> Result<Self, BBSPlusError> {
if messages.is_empty() {
return Err(BBSPlusError::NoMessageToSign);
}
expect_equality!(
messages.len(),
params.supported_message_count(),
BBSPlusError::MessageCountIncompatibleWithSigParams
);
let msg_map: BTreeMap<usize, &E::ScalarField> =
messages.iter().enumerate().map(|(i, e)| (i, e)).collect();
Self::new_with_committed_messages(rng, &E::G1Affine::zero(), msg_map, sk, params)
}
pub fn new_with_committed_messages<R: RngCore>(
rng: &mut R,
commitment: &E::G1Affine,
uncommitted_messages: BTreeMap<usize, &E::ScalarField>,
sk: &SecretKey<E::ScalarField>,
params: &SignatureParams23G1<E>,
) -> Result<Self, BBSPlusError> {
if uncommitted_messages.is_empty() {
return Err(BBSPlusError::NoMessageToSign);
}
if uncommitted_messages.len() > params.supported_message_count() {
return Err(BBSPlusError::MessageCountIncompatibleWithSigParams(
uncommitted_messages.len(),
params.supported_message_count(),
));
}
let b = params.b(uncommitted_messages)?;
let mut e = E::ScalarField::rand(rng);
while (e + sk.0).is_zero() {
e = E::ScalarField::rand(rng)
}
let e_plus_x_inv = (e + sk.0).inverse().unwrap();
let commitment_plus_b = b + commitment;
let A = commitment_plus_b.mul_bigint(e_plus_x_inv.into_bigint());
Ok(Self {
A: A.into_affine(),
e,
})
}
pub fn is_non_zero(&self) -> bool {
!self.A.is_zero()
}
pub fn pre_verify(
&self,
messages: &[E::ScalarField],
params: &PreparedSignatureParams23G1<E>,
) -> Result<E::G1, BBSPlusError> {
if messages.is_empty() {
return Err(BBSPlusError::NoMessageToSign);
}
expect_equality!(
messages.len(),
params.supported_message_count(),
BBSPlusError::MessageCountIncompatibleWithSigParams
);
if !self.is_non_zero() {
return Err(BBSPlusError::ZeroSignature);
}
params.b(messages.iter().enumerate())
}
}
impl<E: Pairing> Signature23G1<E> {
pub fn verify(
&self,
messages: &[E::ScalarField],
pk: impl Into<PreparedPublicKeyG2<E>>,
params: impl Into<PreparedSignatureParams23G1<E>>,
) -> Result<(), BBSPlusError> {
let params = params.into();
let b = self.pre_verify(messages, ¶ms)?;
let Aeb = self.A.mul(self.e) - b;
if !E::multi_pairing(
[
E::G1Prepared::from(self.A),
E::G1Prepared::from(Aeb.into_affine()),
],
[pk.into().0, params.g2],
)
.is_zero()
{
return Err(BBSPlusError::InvalidSignature);
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{setup::KeypairG2, test_serialization};
use ark_bls12_381::{Bls12_381, G1Affine};
use ark_std::{
rand::{rngs::StdRng, SeedableRng},
UniformRand,
};
use std::time::Instant;
type Fr = <Bls12_381 as Pairing>::ScalarField;
#[test]
fn signature_verification() {
let mut rng = StdRng::seed_from_u64(0u64);
let message_count = 20;
let messages: Vec<Fr> = (0..message_count).map(|_| Fr::rand(&mut rng)).collect();
let params = SignatureParams23G1::<Bls12_381>::generate_using_rng(&mut rng, message_count);
let keypair =
KeypairG2::<Bls12_381>::generate_using_rng_and_bbs23_params(&mut rng, ¶ms);
let start = Instant::now();
let sig =
Signature23G1::<Bls12_381>::new(&mut rng, &messages, &keypair.secret_key, ¶ms)
.unwrap();
println!(
"Time to sign multi-message of size {} is {:?}",
message_count,
start.elapsed()
);
let (verif_params, verif_pk) = (
PreparedSignatureParams23G1::from(params.clone()),
PreparedPublicKeyG2::from(keypair.public_key.clone()),
);
let mut zero_sig = sig.clone();
zero_sig.A = G1Affine::zero();
assert!(zero_sig
.verify(&messages, verif_pk.clone(), verif_params.clone())
.is_err());
let start = Instant::now();
sig.verify(&messages, verif_pk, verif_params).unwrap();
println!(
"Time to verify signature over multi-message of size {} is {:?}",
message_count,
start.elapsed()
);
test_serialization!(Signature23G1<Bls12_381>, sig);
drop(sig);
}
}