1use ark_ec::{AffineRepr, CurveGroup};
2
3use super::{multiplication_phase::Phase2Output, utils::compute_R_and_u};
4use ark_ec::pairing::Pairing;
5use ark_ff::{Field, PrimeField, Zero};
6use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
7use ark_std::{
8 collections::{BTreeMap, BTreeSet},
9 rand::RngCore,
10 vec::Vec,
11};
12use digest::{Digest, DynDigest};
13use dock_crypto_utils::expect_equality;
14
15use crate::{
16 error::BBSPlusError, setup::SignatureParams23G1, signature_23::Signature23G1,
17 threshold::randomness_generation_phase::Phase1,
18};
19use dock_crypto_utils::signature::MultiMessageSignatureParams;
20use oblivious_transfer_protocols::{cointoss, zero_sharing, ParticipantId};
21
22#[derive(Clone, Debug, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
25pub struct Phase1Output<F: PrimeField> {
26 pub id: ParticipantId,
27 pub batch_size: u32,
28 pub r: Vec<F>,
30 pub e: Vec<F>,
31 pub masked_signing_key_shares: Vec<F>,
33 pub masked_rs: Vec<F>,
35 pub others: Vec<ParticipantId>,
36}
37
38#[derive(Clone, Debug, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
42pub struct BBSSignatureShare<E: Pairing> {
43 pub id: ParticipantId,
44 pub e: E::ScalarField,
45 pub u: E::ScalarField,
46 pub R: E::G1Affine,
47}
48
49impl<F: PrimeField, const SALT_SIZE: usize> Phase1<F, SALT_SIZE> {
50 pub fn init_for_bbs<R: RngCore, D: Digest>(
51 rng: &mut R,
52 batch_size: u32,
53 id: ParticipantId,
54 others: BTreeSet<ParticipantId>,
55 protocol_id: Vec<u8>,
56 ) -> Result<
57 (
58 Self,
59 cointoss::Commitments,
60 BTreeMap<ParticipantId, cointoss::Commitments>,
61 ),
62 BBSPlusError,
63 > {
64 if others.contains(&id) {
65 return Err(BBSPlusError::ParticipantCannotBePresentInOthers(id));
66 }
67 let r = (0..batch_size).map(|_| F::rand(rng)).collect();
68 let (commitment_protocol, comm) =
70 cointoss::Party::commit::<R, D>(rng, id, batch_size, protocol_id.clone());
71 let (zero_sharing_protocol, comm_zero_share) =
73 zero_sharing::Party::init::<R, D>(rng, id, 2 * batch_size, others, protocol_id);
74 Ok((
75 Self {
76 id,
77 batch_size,
78 r,
79 commitment_protocol,
80 zero_sharing_protocol,
81 },
82 comm,
83 comm_zero_share,
84 ))
85 }
86
87 pub fn finish_for_bbs<D: Default + DynDigest + Clone>(
89 self,
90 signing_key: &F,
91 ) -> Result<Phase1Output<F>, BBSPlusError> {
92 let id = self.id;
94 let batch_size = self.batch_size;
95 let r = self.r.clone();
96 let (others, randomness, masked_signing_key_share, masked_r) =
97 self.compute_randomness_and_arguments_for_multiplication::<D>(signing_key)?;
98 debug_assert_eq!(randomness.len() as u32, batch_size);
99 let e = randomness;
100 Ok(Phase1Output {
101 id,
102 batch_size,
103 r,
104 e,
105 masked_signing_key_shares: masked_signing_key_share,
106 masked_rs: masked_r,
107 others,
108 })
109 }
110}
111
112impl<E: Pairing> BBSSignatureShare<E> {
113 pub fn new(
115 messages: &[E::ScalarField],
116 sig_index_in_batch: usize,
117 phase1: &Phase1Output<E::ScalarField>,
118 phase2: &Phase2Output<E::ScalarField>,
119 sig_params: &SignatureParams23G1<E>,
120 ) -> Result<Self, BBSPlusError> {
121 if messages.is_empty() {
122 return Err(BBSPlusError::NoMessageToSign);
123 }
124 expect_equality!(
125 messages.len(),
126 sig_params.supported_message_count(),
127 BBSPlusError::MessageCountIncompatibleWithSigParams
128 );
129 let msg_map: BTreeMap<usize, &E::ScalarField> =
131 messages.iter().enumerate().map(|(i, e)| (i, e)).collect();
132 Self::new_with_committed_messages(
133 &E::G1Affine::zero(),
134 msg_map,
135 sig_index_in_batch,
136 phase1,
137 phase2,
138 sig_params,
139 )
140 }
141
142 pub fn new_with_committed_messages(
144 commitment: &E::G1Affine,
145 uncommitted_messages: BTreeMap<usize, &E::ScalarField>,
146 sig_index_in_batch: usize,
147 phase1: &Phase1Output<E::ScalarField>,
148 phase2: &Phase2Output<E::ScalarField>,
149 sig_params: &SignatureParams23G1<E>,
150 ) -> Result<Self, BBSPlusError> {
151 let b = sig_params.b(uncommitted_messages)?;
152 let commitment_plus_b = b + commitment;
153 let (R, u) = compute_R_and_u(
154 commitment_plus_b,
155 &phase1.r[sig_index_in_batch],
156 &phase1.e[sig_index_in_batch],
157 &phase1.masked_rs[sig_index_in_batch],
158 &phase1.masked_signing_key_shares[sig_index_in_batch],
159 sig_index_in_batch as u32,
160 phase2,
161 );
162 Ok(Self {
163 id: phase1.id,
164 e: phase1.e[sig_index_in_batch],
165 u,
166 R,
167 })
168 }
169
170 pub fn aggregate(sig_shares: Vec<Self>) -> Result<Signature23G1<E>, BBSPlusError> {
171 let mut sum_R = E::G1::zero();
173 let mut sum_u = E::ScalarField::zero();
174 let mut expected_e = E::ScalarField::zero();
175 for (i, share) in sig_shares.into_iter().enumerate() {
176 if i == 0 {
177 expected_e = share.e;
178 } else {
179 if expected_e != share.e {
180 return Err(BBSPlusError::IncorrectEByParticipant(share.id));
181 }
182 }
183 sum_u += share.u;
184 sum_R += share.R;
185 }
186 let A = sum_R * sum_u.inverse().unwrap();
187 Ok(Signature23G1 {
188 A: A.into_affine(),
189 e: expected_e,
190 })
191 }
192}
193
194#[cfg(test)]
195pub mod tests {
196 use super::*;
197 use crate::{
198 setup::{PublicKeyG2, SecretKey},
199 threshold::{
200 multiplication_phase::Phase2, threshold_bbs_plus::tests::trusted_party_keygen,
201 },
202 };
203 use ark_bls12_381::{Bls12_381, Fr};
204 use ark_ff::Zero;
205 use ark_std::{
206 rand::{rngs::StdRng, SeedableRng},
207 UniformRand,
208 };
209 use blake2::Blake2b512;
210 use oblivious_transfer_protocols::ot_based_multiplication::{
211 dkls18_mul_2p::MultiplicationOTEParams, dkls19_batch_mul_2p::GadgetVector,
212 };
213 use sha3::Shake256;
214 use std::time::{Duration, Instant};
215 use test_utils::ot::do_pairwise_base_ot;
216
217 #[test]
218 fn signing() {
219 let mut rng = StdRng::seed_from_u64(0u64);
220 const BASE_OT_KEY_SIZE: u16 = 128;
221 const KAPPA: u16 = 256;
222 const STATISTICAL_SECURITY_PARAMETER: u16 = 80;
223 let ote_params = MultiplicationOTEParams::<KAPPA, STATISTICAL_SECURITY_PARAMETER> {};
224 let gadget_vector = GadgetVector::<Fr, KAPPA, STATISTICAL_SECURITY_PARAMETER>::new::<
225 Blake2b512,
226 >(ote_params, b"test-gadget-vector");
227
228 let protocol_id = b"test".to_vec();
229
230 let sig_batch_size = 3;
231 let threshold_signers = 5;
232 let total_signers = 8;
233 let all_party_set = (1..=total_signers).into_iter().collect::<BTreeSet<_>>();
234 let threshold_party_set = (1..=threshold_signers).into_iter().collect::<BTreeSet<_>>();
235
236 let (sk, sk_shares) =
238 trusted_party_keygen::<_, Fr>(&mut rng, threshold_signers, total_signers);
239
240 let base_ot_outputs = do_pairwise_base_ot::<BASE_OT_KEY_SIZE>(
242 &mut rng,
243 ote_params.num_base_ot(),
244 total_signers,
245 all_party_set.clone(),
246 );
247
248 let message_count = 5;
249 let params = SignatureParams23G1::<Bls12_381>::generate_using_rng(&mut rng, message_count);
250 let public_key =
251 PublicKeyG2::generate_using_secret_key_and_bbs23_params(&SecretKey(sk), ¶ms);
252
253 println!(
254 "For a batch size of {} BBS signatures and {} signers",
255 sig_batch_size, threshold_signers
256 );
257
258 let mut round1s = vec![];
261 let mut commitments = vec![];
262 let mut commitments_zero_share = vec![];
263 let mut round1outs = vec![];
264
265 let start = Instant::now();
267 for i in 1..=threshold_signers {
268 let mut others = threshold_party_set.clone();
269 others.remove(&i);
270 let (round1, comm, comm_zero) = Phase1::<Fr, 256>::init_for_bbs::<_, Blake2b512>(
271 &mut rng,
272 sig_batch_size,
273 i,
274 others,
275 protocol_id.clone(),
276 )
277 .unwrap();
278 round1s.push(round1);
279 commitments.push(comm);
280 commitments_zero_share.push(comm_zero);
281 }
282
283 for i in 1..=threshold_signers {
285 for j in 1..=threshold_signers {
286 if i != j {
287 round1s[i as usize - 1]
288 .receive_commitment(
289 j,
290 commitments[j as usize - 1].clone(),
291 commitments_zero_share[j as usize - 1]
292 .get(&i)
293 .unwrap()
294 .clone(),
295 )
296 .unwrap();
297 }
298 }
299 }
300
301 for i in 1..=threshold_signers {
303 for j in 1..=threshold_signers {
304 if i != j {
305 let share = round1s[j as usize - 1].get_comm_shares_and_salts();
306 let zero_share = round1s[j as usize - 1]
307 .get_comm_shares_and_salts_for_zero_sharing_protocol_with_other(&i);
308 round1s[i as usize - 1]
309 .receive_shares::<Blake2b512>(j, share, zero_share)
310 .unwrap();
311 }
312 }
313 }
314
315 let mut expected_sk = Fr::zero();
317 for (i, round1) in round1s.into_iter().enumerate() {
318 let out = round1.finish_for_bbs::<Blake2b512>(&sk_shares[i]).unwrap();
319 expected_sk += out.masked_signing_key_shares.iter().sum::<Fr>();
320 round1outs.push(out);
321 }
322 println!("Phase 1 took {:?}", start.elapsed());
323
324 assert_eq!(expected_sk, sk * Fr::from(sig_batch_size));
325 for i in 1..threshold_signers {
326 assert_eq!(round1outs[0].e, round1outs[i as usize].e);
327 }
328
329 let mut round2s = vec![];
330 let mut all_msg_1s = vec![];
331
332 let start = Instant::now();
334 for i in 1..=threshold_signers {
335 let mut others = threshold_party_set.clone();
336 others.remove(&i);
337 let (phase, U) = Phase2::init::<_, Shake256>(
338 &mut rng,
339 i,
340 round1outs[i as usize - 1].masked_signing_key_shares.clone(),
341 round1outs[i as usize - 1].masked_rs.clone(),
342 base_ot_outputs[i as usize - 1].clone(),
343 others,
344 ote_params,
345 &gadget_vector,
346 )
347 .unwrap();
348 round2s.push(phase);
349 all_msg_1s.push((i, U));
350 }
351
352 let mut all_msg_2s = vec![];
354 for (sender_id, msg_1s) in all_msg_1s {
355 for (receiver_id, m) in msg_1s {
356 let m2 = round2s[receiver_id as usize - 1]
357 .receive_message1::<Blake2b512, Shake256>(sender_id, m, &gadget_vector)
358 .unwrap();
359 all_msg_2s.push((receiver_id, sender_id, m2));
360 }
361 }
362
363 for (sender_id, receiver_id, m2) in all_msg_2s {
364 round2s[receiver_id as usize - 1]
365 .receive_message2::<Blake2b512>(sender_id, m2, &gadget_vector)
366 .unwrap();
367 }
368
369 let round2_outputs = round2s.into_iter().map(|p| p.finish()).collect::<Vec<_>>();
370 println!("Phase 2 took {:?}", start.elapsed());
371
372 for i in 1..=threshold_signers {
375 for (j, z_A) in &round2_outputs[i as usize - 1].0.z_A {
376 let z_B = round2_outputs[*j as usize - 1].0.z_B.get(&i).unwrap();
377 for k in 0..sig_batch_size as usize {
378 assert_eq!(
379 z_A.0[k] + z_B.0[k],
380 round1outs[i as usize - 1].masked_signing_key_shares[k]
381 * round1outs[*j as usize - 1].masked_rs[k]
382 );
383 assert_eq!(
384 z_A.1[k] + z_B.1[k],
385 round1outs[i as usize - 1].masked_rs[k]
386 * round1outs[*j as usize - 1].masked_signing_key_shares[k]
387 );
388 }
389 }
390 }
391
392 let mut sig_shares_time = Duration::default();
395 let mut sig_aggr_time = Duration::default();
396 for k in 0..sig_batch_size as usize {
397 let messages = (0..message_count)
398 .into_iter()
399 .map(|_| Fr::rand(&mut rng))
400 .collect::<Vec<_>>();
401
402 let mut shares = vec![];
404 let start = Instant::now();
405 for i in 0..threshold_signers as usize {
406 let share = BBSSignatureShare::new(
407 &messages,
408 k,
409 &round1outs[i],
410 &round2_outputs[i],
411 ¶ms,
412 )
413 .unwrap();
414 shares.push(share);
415 }
416 sig_shares_time += start.elapsed();
417
418 let start = Instant::now();
420 let sig = BBSSignatureShare::aggregate(shares).unwrap();
421 sig_aggr_time += start.elapsed();
422 sig.verify(&messages, public_key.clone(), params.clone())
423 .unwrap();
424 }
425
426 println!("Generating signature shares took {:?}", sig_shares_time);
427 println!("Aggregating signature shares took {:?}", sig_aggr_time);
428 }
429}