Skip to content

Commit afd78fe

Browse files
committed
Remove duplicate Schnorr responses, primarily from proof system
Signed-off-by: lovesh <lovesh.bond@gmail.com>
1 parent 8cae48f commit afd78fe

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+4542
-1245
lines changed

bbs_plus/src/error.rs

+4
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ pub enum BBSPlusError {
5959
SenderEitherNotReadyForResponseOrAlreadySentIt(ParticipantId),
6060
ReceiverEitherNotReadyForHashedKeysOrAlreadyVerifiedIt(ParticipantId),
6161
SSError(SSError),
62+
MissingResponsesNeededForPartialSchnorrProofVerification,
63+
MissingResponsesProvidedForFullSchnorrProofVerification,
64+
NeedEitherPartialOrCompleteSchnorrResponse,
65+
CommonIndicesFoundInRevealedAndSkip,
6266
}
6367

6468
impl From<SchnorrError> for BBSPlusError {

bbs_plus/src/proof.rs

+326-111
Large diffs are not rendered by default.

bbs_plus/src/proof_23_cdl.rs

+187-52
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,24 @@ use ark_std::{
3030
io::Write,
3131
rand::RngCore,
3232
vec::Vec,
33-
One, UniformRand,
33+
UniformRand,
3434
};
3535
use core::mem;
3636
use dock_crypto_utils::{
3737
misc::rand,
3838
randomized_pairing_check::RandomizedPairingChecker,
3939
serde_utils::*,
40-
signature::{split_messages_and_blindings, MessageOrBlinding, MultiMessageSignatureParams},
40+
signature::{
41+
msg_index_map_to_schnorr_response_map, msg_index_to_schnorr_response_index,
42+
schnorr_responses_to_msg_index_map, split_messages_and_blindings, MessageOrBlinding,
43+
MultiMessageSignatureParams,
44+
},
4145
};
4246
use itertools::multiunzip;
4347
use schnorr_pok::{
4448
discrete_log::{PokTwoDiscreteLogs, PokTwoDiscreteLogsProtocol},
4549
error::SchnorrError,
50+
partial::PartialSchnorrResponse,
4651
SchnorrCommitment, SchnorrResponse,
4752
};
4853
use serde::{Deserialize, Serialize};
@@ -99,7 +104,8 @@ pub struct PoKOfSignature23G1Proof<E: Pairing> {
99104
/// Proof of relation `g1 + h1*m1 + h2*m2 +.... + h_i*m_i` = `d*r3 + h1*{-m1} + h2*{-m2} + .... + h_j*{-m_j}` for all disclosed messages `m_i` and for all undisclosed messages `m_j`
100105
#[serde_as(as = "ArkObjectBytes")]
101106
pub T2: E::G1Affine,
102-
pub sc_resp_2: SchnorrResponse<E::G1Affine>,
107+
pub sc_resp_2: Option<SchnorrResponse<E::G1Affine>>,
108+
pub sc_partial_resp_2: Option<PartialSchnorrResponse<E::G1Affine>>,
103109
}
104110

105111
impl<E: Pairing> PoKOfSignature23G1Protocol<E> {
@@ -228,7 +234,38 @@ impl<E: Pairing> PoKOfSignature23G1Protocol<E> {
228234
d: self.d,
229235
sc_resp_1,
230236
T2: self.sc_comm_2.t,
231-
sc_resp_2,
237+
sc_resp_2: Some(sc_resp_2),
238+
sc_partial_resp_2: None,
239+
})
240+
}
241+
242+
pub fn gen_partial_proof(
243+
mut self,
244+
challenge: &E::ScalarField,
245+
revealed_msg_ids: &BTreeSet<usize>,
246+
skip_responses_for: &BTreeSet<usize>,
247+
) -> Result<PoKOfSignature23G1Proof<E>, BBSPlusError> {
248+
if !skip_responses_for.is_disjoint(revealed_msg_ids) {
249+
return Err(BBSPlusError::CommonIndicesFoundInRevealedAndSkip);
250+
}
251+
let sc_resp_1 = mem::take(&mut self.sc_comm_1).gen_proof(challenge);
252+
253+
let wits = schnorr_responses_to_msg_index_map(
254+
mem::take(&mut self.sc_wits_2),
255+
revealed_msg_ids,
256+
skip_responses_for,
257+
);
258+
// Schnorr response for relation `g1 + \sum_{i in D}(h_i*m_i)` = `d*r3 + {h_0}*{-s'} + \sum_{j not in D}(h_j*{-m_j})`
259+
let sc_resp_2 = self.sc_comm_2.partial_response(wits, challenge)?;
260+
261+
Ok(PoKOfSignature23G1Proof {
262+
A_bar: self.A_bar,
263+
B_bar: self.B_bar,
264+
d: self.d,
265+
sc_resp_1,
266+
T2: self.sc_comm_2.t,
267+
sc_resp_2: None,
268+
sc_partial_resp_2: Some(sc_resp_2),
232269
})
233270
}
234271

@@ -271,42 +308,76 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
271308
pk: impl Into<PreparedPublicKeyG2<E>>,
272309
params: impl Into<PreparedSignatureParams23G1<E>>,
273310
) -> Result<(), BBSPlusError> {
274-
let params = params.into();
275-
let g1 = params.g1;
276-
let g2 = params.g2;
277-
let h = params.h;
278-
self.verify_except_pairings(revealed_msgs, challenge, g1, h)?;
311+
self._verify(revealed_msgs, challenge, pk, params, None)
312+
}
279313

280-
// Verify the randomized signature
281-
if !E::multi_pairing(
282-
[
283-
E::G1Prepared::from(self.A_bar),
284-
E::G1Prepared::from(-(self.B_bar.into_group())),
285-
],
286-
[pk.into().0, g2],
314+
pub fn verify_with_randomized_pairing_checker(
315+
&self,
316+
revealed_msgs: &BTreeMap<usize, E::ScalarField>,
317+
challenge: &E::ScalarField,
318+
pk: impl Into<PreparedPublicKeyG2<E>>,
319+
params: impl Into<PreparedSignatureParams23G1<E>>,
320+
pairing_checker: &mut RandomizedPairingChecker<E>,
321+
) -> Result<(), BBSPlusError> {
322+
self._verify_with_randomized_pairing_checker(
323+
revealed_msgs,
324+
challenge,
325+
pk,
326+
params,
327+
pairing_checker,
328+
None,
287329
)
288-
.is_zero()
289-
{
290-
return Err(BBSPlusError::PairingCheckFailed);
291-
}
292-
Ok(())
293330
}
294331

295-
pub fn verify_with_randomized_pairing_checker(
332+
pub fn verify_partial(
333+
&self,
334+
revealed_msgs: &BTreeMap<usize, E::ScalarField>,
335+
challenge: &E::ScalarField,
336+
pk: impl Into<PreparedPublicKeyG2<E>>,
337+
params: impl Into<PreparedSignatureParams23G1<E>>,
338+
missing_responses: BTreeMap<usize, E::ScalarField>,
339+
) -> Result<(), BBSPlusError> {
340+
self._verify(
341+
revealed_msgs,
342+
challenge,
343+
pk,
344+
params,
345+
Some(missing_responses),
346+
)
347+
}
348+
349+
pub fn verify_partial_with_randomized_pairing_checker(
296350
&self,
297351
revealed_msgs: &BTreeMap<usize, E::ScalarField>,
298352
challenge: &E::ScalarField,
299353
pk: impl Into<PreparedPublicKeyG2<E>>,
300354
params: impl Into<PreparedSignatureParams23G1<E>>,
301355
pairing_checker: &mut RandomizedPairingChecker<E>,
356+
missing_responses: BTreeMap<usize, E::ScalarField>,
302357
) -> Result<(), BBSPlusError> {
303-
let params = params.into();
304-
let g1 = params.g1;
305-
let g2 = params.g2;
306-
let h = params.h;
307-
self.verify_except_pairings(revealed_msgs, challenge, g1, h)?;
308-
pairing_checker.add_sources(&self.A_bar, pk.into().0, &self.B_bar, g2);
309-
Ok(())
358+
self._verify_with_randomized_pairing_checker(
359+
revealed_msgs,
360+
challenge,
361+
pk,
362+
params,
363+
pairing_checker,
364+
Some(missing_responses),
365+
)
366+
}
367+
368+
pub fn get_responses(
369+
&self,
370+
msg_ids: &BTreeSet<usize>,
371+
revealed_msg_ids: &BTreeSet<usize>,
372+
) -> Result<BTreeMap<usize, E::ScalarField>, BBSPlusError> {
373+
let mut resps = BTreeMap::new();
374+
for msg_idx in msg_ids {
375+
resps.insert(
376+
*msg_idx,
377+
*self.get_resp_for_message(*msg_idx, revealed_msg_ids)?,
378+
);
379+
}
380+
Ok(resps)
310381
}
311382

312383
/// For the verifier to independently calculate the challenge
@@ -335,18 +406,62 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
335406
msg_idx: usize,
336407
revealed_msg_ids: &BTreeSet<usize>,
337408
) -> Result<&E::ScalarField, BBSPlusError> {
338-
// Revealed messages are not part of Schnorr protocol
339-
if revealed_msg_ids.contains(&msg_idx) {
340-
return Err(BBSPlusError::InvalidMsgIdxForResponse(msg_idx));
409+
let adjusted_idx = msg_index_to_schnorr_response_index(msg_idx, revealed_msg_ids)
410+
.ok_or_else(|| BBSPlusError::InvalidMsgIdxForResponse(msg_idx))?;
411+
if let Some(resp) = self.sc_resp_2.as_ref() {
412+
Ok(resp.get_response(adjusted_idx)?)
413+
} else if let Some(resp) = self.sc_partial_resp_2.as_ref() {
414+
Ok(resp.get_response(adjusted_idx)?)
415+
} else {
416+
Err(BBSPlusError::NeedEitherPartialOrCompleteSchnorrResponse)
341417
}
342-
// Adjust message index as the revealed messages are not part of the Schnorr protocol
343-
let mut adjusted_idx = msg_idx;
344-
for i in revealed_msg_ids {
345-
if *i < msg_idx {
346-
adjusted_idx -= 1;
347-
}
418+
}
419+
420+
pub fn _verify(
421+
&self,
422+
revealed_msgs: &BTreeMap<usize, E::ScalarField>,
423+
challenge: &E::ScalarField,
424+
pk: impl Into<PreparedPublicKeyG2<E>>,
425+
params: impl Into<PreparedSignatureParams23G1<E>>,
426+
missing_responses: Option<BTreeMap<usize, E::ScalarField>>,
427+
) -> Result<(), BBSPlusError> {
428+
let params = params.into();
429+
let g1 = params.g1;
430+
let g2 = params.g2;
431+
let h = params.h;
432+
self.verify_except_pairings(revealed_msgs, challenge, g1, h, missing_responses)?;
433+
434+
// Verify the randomized signature
435+
if !E::multi_pairing(
436+
[
437+
E::G1Prepared::from(self.A_bar),
438+
E::G1Prepared::from(-(self.B_bar.into_group())),
439+
],
440+
[pk.into().0, g2],
441+
)
442+
.is_zero()
443+
{
444+
return Err(BBSPlusError::PairingCheckFailed);
348445
}
349-
Ok(self.sc_resp_2.get_response(adjusted_idx)?)
446+
Ok(())
447+
}
448+
449+
pub fn _verify_with_randomized_pairing_checker(
450+
&self,
451+
revealed_msgs: &BTreeMap<usize, E::ScalarField>,
452+
challenge: &E::ScalarField,
453+
pk: impl Into<PreparedPublicKeyG2<E>>,
454+
params: impl Into<PreparedSignatureParams23G1<E>>,
455+
pairing_checker: &mut RandomizedPairingChecker<E>,
456+
missing_responses: Option<BTreeMap<usize, E::ScalarField>>,
457+
) -> Result<(), BBSPlusError> {
458+
let params = params.into();
459+
let g1 = params.g1;
460+
let g2 = params.g2;
461+
let h = params.h;
462+
self.verify_except_pairings(revealed_msgs, challenge, g1, h, missing_responses)?;
463+
pairing_checker.add_sources(&self.A_bar, pk.into().0, &self.B_bar, g2);
464+
Ok(())
350465
}
351466

352467
pub fn verify_schnorr_proofs(
@@ -355,6 +470,7 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
355470
challenge: &E::ScalarField,
356471
g1: E::G1Affine,
357472
h: Vec<E::G1Affine>,
473+
missing_responses: Option<BTreeMap<usize, E::ScalarField>>,
358474
) -> Result<(), BBSPlusError> {
359475
// Verify the 1st Schnorr proof
360476
if !self
@@ -367,10 +483,8 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
367483
// Verify the 2nd Schnorr proof
368484
let mut bases_2 = Vec::with_capacity(1 + h.len() - revealed_msgs.len());
369485

370-
let mut bases_revealed = Vec::with_capacity(1 + revealed_msgs.len());
371-
let mut exponents = Vec::with_capacity(1 + revealed_msgs.len());
372-
bases_revealed.push(g1);
373-
exponents.push(E::ScalarField::one());
486+
let mut bases_revealed = Vec::with_capacity(revealed_msgs.len());
487+
let mut exponents = Vec::with_capacity(revealed_msgs.len());
374488
for i in 0..h.len() {
375489
if revealed_msgs.contains_key(&i) {
376490
let message = revealed_msgs.get(&i).unwrap();
@@ -382,17 +496,37 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
382496
}
383497
bases_2.push(self.d);
384498
// pr = -g1 + \sum_{i in D}(h_i*{-m_i}) = -(g1 + \sum_{i in D}(h_i*{m_i}))
385-
let pr = -E::G1::msm_unchecked(&bases_revealed, &exponents);
499+
let pr = -E::G1::msm_unchecked(&bases_revealed, &exponents) - g1;
386500
let pr = pr.into_affine();
387-
match self.sc_resp_2.is_valid(&bases_2, &pr, &self.T2, challenge) {
388-
Ok(()) => (),
389-
Err(SchnorrError::InvalidResponse) => {
390-
return Err(BBSPlusError::SecondSchnorrVerificationFailed)
501+
if let Some(resp) = &self.sc_resp_2 {
502+
if missing_responses.is_some() {
503+
return Err(BBSPlusError::MissingResponsesProvidedForFullSchnorrProofVerification);
391504
}
392-
Err(other) => return Err(BBSPlusError::SchnorrError(other)),
505+
return match resp.is_valid(&bases_2, &pr, &self.T2, challenge) {
506+
Ok(()) => Ok(()),
507+
Err(SchnorrError::InvalidResponse) => {
508+
Err(BBSPlusError::SecondSchnorrVerificationFailed)
509+
}
510+
Err(other) => Err(BBSPlusError::SchnorrError(other)),
511+
};
512+
} else if let Some(resp) = &self.sc_partial_resp_2 {
513+
if missing_responses.is_none() {
514+
return Err(BBSPlusError::MissingResponsesNeededForPartialSchnorrProofVerification);
515+
}
516+
let adjusted_missing = msg_index_map_to_schnorr_response_map(
517+
missing_responses.unwrap(),
518+
revealed_msgs.keys(),
519+
);
520+
return match resp.is_valid(&bases_2, &pr, &self.T2, challenge, adjusted_missing) {
521+
Ok(()) => Ok(()),
522+
Err(SchnorrError::InvalidResponse) => {
523+
Err(BBSPlusError::SecondSchnorrVerificationFailed)
524+
}
525+
Err(other) => Err(BBSPlusError::SchnorrError(other)),
526+
};
527+
} else {
528+
Err(BBSPlusError::NeedEitherPartialOrCompleteSchnorrResponse)
393529
}
394-
395-
Ok(())
396530
}
397531

398532
/// Verify the proof except the pairing equations. This is useful when doing several verifications (of this
@@ -403,11 +537,12 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
403537
challenge: &E::ScalarField,
404538
g1: E::G1Affine,
405539
h: Vec<E::G1Affine>,
540+
missing_responses: Option<BTreeMap<usize, E::ScalarField>>,
406541
) -> Result<(), BBSPlusError> {
407542
if self.A_bar.is_zero() {
408543
return Err(BBSPlusError::ZeroSignature);
409544
}
410-
self.verify_schnorr_proofs(revealed_msgs, challenge, g1, h)
545+
self.verify_schnorr_proofs(revealed_msgs, challenge, g1, h, missing_responses)
411546
}
412547
}
413548

0 commit comments

Comments
 (0)