Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 10 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Assuming you already have proofs-of-possession, then you'll want to do aggregati
The library offers method for generating and verifying proof of positions both based on BLS and [Schnorr Signature](https://en.wikipedia.org/wiki/Schnorr_signature) which is faster to verify than when using BLS signature itself as proof of position. The following example demonstrate how to generate and verify proof of positions and then using `SignatureAggregatorAssumingPoP` to batch and verify multiple BLS signatures.

```rust
use w3f_bls::{Keypair,PublicKey,ZBLS,Message,Signed, ProofOfPossessionGenerator, ProofOfPossession, experimental::schnorr_pop::{SchnorrPoP}, multi_pop_aggregator::MultiMessageSignatureAggregatorAssumingPoP};
use w3f_bls::{Keypair,PublicKey,ZBLS,Message,Signed, ProofOfPossessionGenerator, ProofOfPossession, experimental::schnorr_pop::{SchnorrPoP}, pop_aggregator::SignatureAggregatorAssumingPoP};
use sha2::Sha256;

let mut keypairs = [Keypair::<ZBLS>::generate(::rand::thread_rng()), Keypair::<ZBLS>::generate(::rand::thread_rng())];
Expand All @@ -92,7 +92,7 @@ let pops = keypairs.iter_mut().map(|k|(ProofOfPossessionGenerator::<ZBLS, Sha256
let publickeys = publickeys.iter().zip(pops.iter()).map(|(publickey, pop) | {assert!(ProofOfPossession::<ZBLS, Sha256, PublicKey<ZBLS>>::verify(pop,publickey)); publickey}).collect::<Vec<_>>();

let batch_poped = msgs.iter().zip(publickeys).zip(sigs).fold(
MultiMessageSignatureAggregatorAssumingPoP::<ZBLS>::new(),
SignatureAggregatorAssumingPoP::<ZBLS>::new(),
|mut bpop,((message, publickey),sig)| { bpop.add_message_n_publickey(message, &publickey); bpop.add_signature(&sig); bpop }
);
assert!(batch_poped.verify())
Expand All @@ -106,12 +106,11 @@ The scheme introduced in [`our recent paper`](https://eprint.iacr.org/2022/1611)
```rust
use sha2::Sha256;
use ark_bls12_377::Bls12_377;
use ark_ff::Zero;
use rand::thread_rng;

use w3f_bls::{
single_pop_aggregator::SignatureAggregatorAssumingPoP, DoubleNuggetBLS, EngineBLS, Keypair,
Message, NuggetPublicKey, PublicKey, PublicKeyInSignatureGroup, Signed, TinyBLS, TinyBLS377,
pop_aggregator::SignatureAggregatorAssumingPoP, DoubleNuggetBLS, EngineBLS, Keypair,
Message, NuggetPublicKey, PublicKeyInSignatureGroup, TinyBLS, TinyBLS377,
};


Expand All @@ -125,28 +124,13 @@ let pub_keys_in_sig_grp: Vec<PublicKeyInSignatureGroup<TinyBLS377>> = keypairs
.map(|k| DoubleNuggetBLS::<TinyBLS377>::into_nugget_double_public_key(k).into_public_key_in_signature_group())
.collect();

let mut prover_aggregator =
SignatureAggregatorAssumingPoP::<TinyBLS377>::new(message.clone());
let mut aggregated_public_key =
PublicKey::<TinyBLS377>(<TinyBLS377 as EngineBLS>::PublicKeyGroup::zero());
let mut verifier_aggregator = SignatureAggregatorAssumingPoP::<TinyBLS377>::new();

//sign and aggegate
let _ = keypairs
.iter_mut()
.map(|k| {
prover_aggregator.add_signature(&k.sign(&message));
aggregated_public_key.0 += k.public.0;
})
.count();

let mut verifier_aggregator = SignatureAggregatorAssumingPoP::<TinyBLS377>::new(message);

verifier_aggregator.add_signature(&(&prover_aggregator).signature());

//aggregate public keys in signature group
verifier_aggregator.add_publickey(&aggregated_public_key);

pub_keys_in_sig_grp.iter().for_each(|pk| {verifier_aggregator.add_auxiliary_public_key(pk);});
//sign, aggregate, and add (publickey, aux) pairs
for (k, aux) in keypairs.iter_mut().zip(pub_keys_in_sig_grp.iter()) {
verifier_aggregator.add_signature(&k.sign(&message));
verifier_aggregator.add_message_n_publickey(&message, &(k.public, *aux));
}

assert!(
verifier_aggregator.verify_using_aggregated_auxiliary_public_keys::<Sha256>(),
Expand Down
31 changes: 8 additions & 23 deletions examples/aggregate_with_public_key_in_signature_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
use sha2::Sha256;
#[cfg(feature = "std")]
use w3f_bls::{
single_pop_aggregator::SignatureAggregatorAssumingPoP, EngineBLS, Keypair, Message, NuggetBLS,
PublicKey, PublicKeyInSignatureGroup, Signed, TinyBLS, TinyBLS377,
pop_aggregator::SignatureAggregatorAssumingPoP, EngineBLS, Keypair, Message, NuggetBLS,
PublicKeyInSignatureGroup, TinyBLS, TinyBLS377,
};

#[cfg(feature = "std")]
use ark_bls12_377::Bls12_377;
#[cfg(feature = "std")]
use ark_ff::Zero;
#[cfg(feature = "std")]
use rand::thread_rng;

/// Run using
Expand All @@ -31,26 +29,13 @@ fn main() {
.iter()
.map(|k| NuggetBLS::<_, <EB as EngineBLS>::SignatureGroup>::into_public_key_in_signature_group(k))
.collect();
let mut prover_aggregator =
SignatureAggregatorAssumingPoP::<TinyBLS377>::new(message.clone());
let mut aggregated_public_key =
PublicKey::<TinyBLS377>(<TinyBLS377 as EngineBLS>::PublicKeyGroup::zero());

//sign and aggegate
keypairs.iter_mut().for_each(|k| {
prover_aggregator.add_signature(&k.sign(&message));
aggregated_public_key.0 += k.public.0;
});

let mut verifier_aggregator = SignatureAggregatorAssumingPoP::<TinyBLS377>::new(message);
//get the signature and already aggregated public key from the prover
verifier_aggregator.add_signature(&(&prover_aggregator).signature());
verifier_aggregator.add_publickey(&aggregated_public_key);
let mut verifier_aggregator = SignatureAggregatorAssumingPoP::<TinyBLS377>::new();

//aggregate public keys in signature group
pub_keys_in_sig_grp.iter().for_each(|pk| {
verifier_aggregator.add_auxiliary_public_key(pk);
});
//sign, aggregate, and add (publickey, aux) pairs
for (k, aux) in keypairs.iter_mut().zip(pub_keys_in_sig_grp.iter()) {
verifier_aggregator.add_signature(&k.sign(&message));
verifier_aggregator.add_message_n_publickey(&message, &(k.public, *aux));
}

assert!(
verifier_aggregator.verify_using_aggregated_auxiliary_public_keys::<Sha256>(),
Expand Down
4 changes: 2 additions & 2 deletions examples/experimental/aggregated_with_pop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use sha2::Sha256;
#[cfg(feature = "std")]
use w3f_bls::{
experimental::schnorr_pop::SchnorrPoP,
multi_pop_aggregator::MultiMessageSignatureAggregatorAssumingPoP,
pop_aggregator::SignatureAggregatorAssumingPoP,
Keypair, Message, ProofOfPossession, ProofOfPossessionGenerator, PublicKey, Signed, ZBLS,
};

Expand Down Expand Up @@ -53,7 +53,7 @@ fn main() {

//now that we have confidence in keys we can verify the batched signature
let batch_poped = msgs.iter().zip(publickeys).zip(sigs).fold(
MultiMessageSignatureAggregatorAssumingPoP::<ZBLS>::new(),
SignatureAggregatorAssumingPoP::<ZBLS>::new(),
|mut bpop, ((message, publickey), sig)| {
bpop.add_message_n_publickey(message, &publickey);
bpop.add_signature(&sig);
Expand Down
55 changes: 52 additions & 3 deletions src/chaum_pedersen_signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::dual_scalar_mul::DualScalarMultiplication;
use crate::engine::EngineBLS;
use crate::nugget::{NuggetBLS, NuggetPublicKey, NuggetSignature};
use crate::serialize::SerializableToBytes;
use crate::{Message, SecretKeyVT};
use crate::{Message, SecretKey, SecretKeyVT};

pub type DLEQProof<E> = (<E as EngineBLS>::Scalar, <E as EngineBLS>::Scalar);
pub type ChaumPedersenSignature<E> = NuggetSignature<E>;
Expand Down Expand Up @@ -322,10 +322,12 @@ where
&self,
message_point_as_bytes: &Vec<u8>,
) -> <<E as EngineBLS>::PublicKeyGroup as PrimeGroup>::ScalarField {
let secret_key_as_bytes = self.to_bytes();

let mut secret_key_hasher = H::default();

let mut secret_key_as_bytes = self.to_bytes();
secret_key_hasher.update(secret_key_as_bytes.as_slice());
::zeroize::Zeroize::zeroize(secret_key_as_bytes.as_mut_slice());

let hashed_secret_key = secret_key_hasher.finalize_fixed_reset().to_vec();

let hasher = <DefaultFieldHasher<H> as HashToField<
Expand All @@ -336,6 +338,53 @@ where
}
}

/// Side-channel-protected variant: BLS signing goes through
/// `SecretKey::seeded_sign` (resplits the key with deterministic
/// randomness), while DLEQ proof generation and witness derivation
/// delegate to the vartime form, which is acceptable because they
/// operate over auxiliary scalars rather than the long-term key.
impl<E: EngineBLS, S: CurveGroup, H: FixedOutputReset + Default + Clone>
ChaumPedersenSigner<E, S, H> for SecretKey<E>
where
S: PrimeGroup<ScalarField = E::Scalar> + SerializableToBytes,
{
fn generate_cp_signature(&mut self, message: &Message) -> ChaumPedersenSignature<E> {
let bls_signature = self.seeded_sign(message);
let dleq = <Self as ChaumPedersenSigner<E, S, H>>::generate_dleq_proof(
self,
message,
bls_signature.0,
);
NuggetSignature(bls_signature.0, dleq)
}

fn generate_dleq_proof(
&mut self,
message: &Message,
bls_signature: E::SignatureGroup,
) -> DLEQProof<E> {
<SecretKeyVT<E> as ChaumPedersenSigner<E, S, H>>::generate_dleq_proof(
&mut self.into_vartime(),
message,
bls_signature,
)
}

fn generate_witness_scaler(
&self,
_message_point_as_bytes: &Vec<u8>,
) -> <<E as EngineBLS>::PublicKeyGroup as PrimeGroup>::ScalarField {
// Unreachable: `generate_dleq_proof` for `SecretKey` delegates to
// the `SecretKeyVT` impl, which calls its own `generate_witness_scaler`.
// Trait coherence forces us to provide a body here, but no caller
// ever lands on it.
unimplemented!(
"SecretKey::generate_witness_scaler is never called; \
dleq generation delegates to SecretKeyVT"
)
}
}

#[cfg(all(test, feature = "std"))]
mod tests {
use rand::thread_rng;
Expand Down
28 changes: 25 additions & 3 deletions src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use ark_ec::{
};
use ark_ff::field_hashers::{DefaultFieldHasher, HashToField};
use ark_ff::{Field, PrimeField, UniformRand, Zero};
use ark_serialize::CanonicalSerialize;
use ark_serialize::{CanonicalSerialize, Valid};
use rand::Rng;
use rand_core::RngCore;

Expand Down Expand Up @@ -198,8 +198,7 @@ pub trait EngineBLS {
signature,
)];
Self::final_exponentiation(Self::miller_loop(inputs.into_iter().map(|t| t).chain(&lhs)))
.unwrap()
== (PairingOutput::<Self::Engine>::zero()) //zero is the target_field::one !!
== Some(PairingOutput::<Self::Engine>::zero()) //zero is the target_field::one !!
}

/// Prepared negative of the generator of the public key curve.
Expand All @@ -219,6 +218,29 @@ pub trait EngineBLS {
Self::PublicKeyPrepared::from(g_affine)
}

/// Subgroup-membership check for a public-key-group point.
/// Used during signature verification (identity is allowed there).
fn verify_public_key_in_public_key_subgroup(g: &Self::PublicKeyGroupAffine) -> bool {
g.check().is_ok()
}

/// Subgroup-membership check for a signature-group point.
/// Used during signature verification.
fn verify_signature_in_signature_subgroup(g: &Self::SignatureGroupAffine) -> bool {
g.check().is_ok()
}

/// Reject public keys that are the identity element or not in the
/// prime-order subgroup. Defends PoP verification against inputs
/// that bypass the deserialization-time check — e.g. direct
/// tuple-struct construction, or aggregates that sum to the identity.
///
/// Implements `KeyValidate` from
/// <https://www.ietf.org/archive/id/draft-irtf-cfrg-bls-signature-06.html#name-validating-public-keys>.
fn validate_public_key(g: &Self::PublicKeyGroupAffine) -> bool {
!g.is_zero() && Self::verify_public_key_in_public_key_subgroup(g)
}

/// Process the signature to be use in pairing. This has to be
/// implemented by the type of BLS system implementing the engine
/// by calling either prepare_g1 or prepare_g2 based on which group
Expand Down
12 changes: 6 additions & 6 deletions src/experimental/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ extern crate test;
const NO_OF_MULTI_SIG_SIGNERS: usize = 100;
use crate::chaum_pedersen_signature::ChaumPedersenSigner;
use crate::chaum_pedersen_signature::ChaumPedersenVerifier;
use crate::multi_pop_aggregator::MultiMessageSignatureAggregatorAssumingPoP;
use crate::pop_aggregator::SignatureAggregatorAssumingPoP;
use crate::Keypair;
use crate::Message;
use crate::Signature as BLSSignature;
Expand Down Expand Up @@ -55,15 +55,15 @@ use crate::PublicKeyInSignatureGroup;
// let mut pub_keys_in_sig_grp : Vec<PublicKeyInSignatureGroup<TinyBLS377>> = keypairs.iter().map(|k| k.into_public_key_in_signature_group()).collect();

// let mut aggregated_public_key = PublicKey::<TinyBLS377>(<TinyBLS377 as EngineBLS>::PublicKeyGroup::zero());
// let mut aggregator = MultiMessageSignatureAggregatorAssumingPoP::<TinyBLS377>::new();
// let mut aggregator = SignatureAggregatorAssumingPoP::<TinyBLS377>::new();

// for k in &mut keypairs {
// aggregator.aggregate(&k.signed_message(message));
// aggregated_public_key.0 += k.public.0;
// }

// b.iter(|| {
// let mut verifier_aggregator = MultiMessageSignatureAggregatorAssumingPoP::<TinyBLS377>::new();
// let mut verifier_aggregator = SignatureAggregatorAssumingPoP::<TinyBLS377>::new();
// let mut verifier_aggregated_public_key = PublicKey::<TinyBLS377>(<TinyBLS377 as EngineBLS>::PublicKeyGroup::zero());

// verifier_aggregator.add_signature(&aggregator.signature);
Expand All @@ -85,7 +85,7 @@ use crate::PublicKeyInSignatureGroup;
// let message = Message::new(b"ctx",b"test message");

// b.iter(|| {
// let mut aggregator = MultiMessageSignatureAggregatorAssumingPoP::<TinyBLS377>::new();
// let mut aggregator = SignatureAggregatorAssumingPoP::<TinyBLS377>::new();
// let mut aggregated_public_key = PublicKey::<TinyBLS377>(<TinyBLS377 as EngineBLS>::PublicKeyGroup::zero());

// for k in &mut keypairs {
Expand All @@ -102,7 +102,7 @@ use crate::PublicKeyInSignatureGroup;
// let mut keypairs = generate_many_keypairs(NO_OF_MULTI_SIG_SIGNERS);
// let mut pub_keys_in_sig_grp : Vec<PublicKeyInSignatureGroup<TinyBLS377>> = keypairs.iter().map(|k| k.into_public_key_in_signature_group()).collect();

// let mut aggregator = MultiMessageSignatureAggregatorAssumingPoP::<TinyBLS377>::new();
// let mut aggregator = SignatureAggregatorAssumingPoP::<TinyBLS377>::new();
// let mut aggregated_public_key = PublicKey::<TinyBLS377>(<TinyBLS377 as EngineBLS>::PublicKeyGroup::zero());

// for k in &mut keypairs {
Expand All @@ -111,7 +111,7 @@ use crate::PublicKeyInSignatureGroup;
// }

// b.iter(|| {
// let mut verifier_aggregator = MultiMessageSignatureAggregatorAssumingPoP::<TinyBLS377>::new();
// let mut verifier_aggregator = SignatureAggregatorAssumingPoP::<TinyBLS377>::new();

// verifier_aggregator.add_signature(&aggregator.signature);
// verifier_aggregator.add_message_n_publickey(&message, &aggregated_public_key);
Expand Down
5 changes: 2 additions & 3 deletions src/experimental/bit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -660,8 +660,7 @@ mod tests {
assert!(bitsig1.merge(&bitsig2).is_err());

let mut multimsg =
crate::multi_pop_aggregator::MultiMessageSignatureAggregatorAssumingPoP::<ZBLS>::new(
);
crate::pop_aggregator::SignatureAggregatorAssumingPoP::<ZBLS>::new();
multimsg.aggregate(&bitsig1);
multimsg.aggregate(&bitsig2);
assert!(multimsg.verify()); // verifiers::verify_with_distinct_messages(&dms,true)
Expand All @@ -687,7 +686,7 @@ mod tests {

let mut countsig = CountSignedMessage::<ZBLS, _>::new(pop.clone(), msg1);
assert!(countsig.signers.len() == 1);
assert!(countsig.verify()); // verifiers::verify_with_distinct_messages(&dms,true)
assert!(countsig.verify());
assert!(countsig.add_bitsig(&bitsig1).is_ok());
assert!(bitsig1.signature == countsig.signature);
assert!(countsig.signers.len() == 1);
Expand Down
2 changes: 1 addition & 1 deletion src/experimental/delinear.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl<E: EngineBLS> Delinearized<E> {
let (x, y) = array_refs!(&b, 8, 8);
let mut x: <E::Scalar as PrimeField>::BigInt = u64::from_le_bytes(*x).into();
let y: <E::Scalar as PrimeField>::BigInt = u64::from_le_bytes(*y).into();
x <<= 6; //warning: use of deprecated method `ark_ff::BigInteger::muln`: please use the operator `<<` instead : x.muln(64);
x <<= 64; //warning: use of deprecated method `ark_ff::BigInteger::muln`: please use the operator `<<` instead : x.muln(64);
x.add_with_carry(&y);
<E::Scalar as PrimeField>::from_bigint(x).unwrap()
}
Expand Down
4 changes: 3 additions & 1 deletion src/experimental/schnorr_pop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ impl<E: EngineBLS, H: FixedOutputReset + Default + Clone + 'static> BLSSchnorrPo
//The pseudo random witness is generated similar to eddsa witness
//hash(secret_key|publick_key)
fn witness_scalar(&self) -> <<E as EngineBLS>::PublicKeyGroup as PrimeGroup>::ScalarField {
let secret_key_as_bytes = self.secret.to_bytes();
let mut secret_key_as_bytes = self.secret.to_bytes();
let public_key_as_bytes = <E as EngineBLS>::public_key_point_to_byte(&self.public.0);

let mut secret_key_hasher = H::default();
secret_key_hasher.update(secret_key_as_bytes.as_slice());
::zeroize::Zeroize::zeroize(secret_key_as_bytes.as_mut_slice());

let hashed_secret_key = secret_key_hasher.finalize_fixed_reset().to_vec();

let hasher = <DefaultFieldHasher<H> as HashToField<
Expand Down
Loading