Skip to content

Commit

Permalink
Remove duplicate Schnorr responses, primarily from proof system
Browse files Browse the repository at this point in the history
Signed-off-by: lovesh <[email protected]>
  • Loading branch information
lovesh committed Jul 17, 2024
1 parent 8cae48f commit afd78fe
Show file tree
Hide file tree
Showing 72 changed files with 4,542 additions and 1,245 deletions.
4 changes: 4 additions & 0 deletions bbs_plus/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ pub enum BBSPlusError {
SenderEitherNotReadyForResponseOrAlreadySentIt(ParticipantId),
ReceiverEitherNotReadyForHashedKeysOrAlreadyVerifiedIt(ParticipantId),
SSError(SSError),
MissingResponsesNeededForPartialSchnorrProofVerification,
MissingResponsesProvidedForFullSchnorrProofVerification,
NeedEitherPartialOrCompleteSchnorrResponse,
CommonIndicesFoundInRevealedAndSkip,
}

impl From<SchnorrError> for BBSPlusError {
Expand Down
437 changes: 326 additions & 111 deletions bbs_plus/src/proof.rs

Large diffs are not rendered by default.

239 changes: 187 additions & 52 deletions bbs_plus/src/proof_23_cdl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,24 @@ use ark_std::{
io::Write,
rand::RngCore,
vec::Vec,
One, UniformRand,
UniformRand,
};
use core::mem;
use dock_crypto_utils::{
misc::rand,
randomized_pairing_check::RandomizedPairingChecker,
serde_utils::*,
signature::{split_messages_and_blindings, MessageOrBlinding, MultiMessageSignatureParams},
signature::{
msg_index_map_to_schnorr_response_map, msg_index_to_schnorr_response_index,
schnorr_responses_to_msg_index_map, split_messages_and_blindings, MessageOrBlinding,
MultiMessageSignatureParams,
},
};
use itertools::multiunzip;
use schnorr_pok::{
discrete_log::{PokTwoDiscreteLogs, PokTwoDiscreteLogsProtocol},
error::SchnorrError,
partial::PartialSchnorrResponse,
SchnorrCommitment, SchnorrResponse,
};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -99,7 +104,8 @@ pub struct PoKOfSignature23G1Proof<E: Pairing> {
/// 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`
#[serde_as(as = "ArkObjectBytes")]
pub T2: E::G1Affine,
pub sc_resp_2: SchnorrResponse<E::G1Affine>,
pub sc_resp_2: Option<SchnorrResponse<E::G1Affine>>,
pub sc_partial_resp_2: Option<PartialSchnorrResponse<E::G1Affine>>,
}

impl<E: Pairing> PoKOfSignature23G1Protocol<E> {
Expand Down Expand Up @@ -228,7 +234,38 @@ impl<E: Pairing> PoKOfSignature23G1Protocol<E> {
d: self.d,
sc_resp_1,
T2: self.sc_comm_2.t,
sc_resp_2,
sc_resp_2: Some(sc_resp_2),
sc_partial_resp_2: None,
})
}

pub fn gen_partial_proof(
mut self,
challenge: &E::ScalarField,
revealed_msg_ids: &BTreeSet<usize>,
skip_responses_for: &BTreeSet<usize>,
) -> Result<PoKOfSignature23G1Proof<E>, BBSPlusError> {
if !skip_responses_for.is_disjoint(revealed_msg_ids) {
return Err(BBSPlusError::CommonIndicesFoundInRevealedAndSkip);
}
let sc_resp_1 = mem::take(&mut self.sc_comm_1).gen_proof(challenge);

let wits = schnorr_responses_to_msg_index_map(
mem::take(&mut self.sc_wits_2),
revealed_msg_ids,
skip_responses_for,
);
// 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})`
let sc_resp_2 = self.sc_comm_2.partial_response(wits, challenge)?;

Ok(PoKOfSignature23G1Proof {
A_bar: self.A_bar,
B_bar: self.B_bar,
d: self.d,
sc_resp_1,
T2: self.sc_comm_2.t,
sc_resp_2: None,
sc_partial_resp_2: Some(sc_resp_2),
})
}

Expand Down Expand Up @@ -271,42 +308,76 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
pk: impl Into<PreparedPublicKeyG2<E>>,
params: impl Into<PreparedSignatureParams23G1<E>>,
) -> Result<(), BBSPlusError> {
let params = params.into();
let g1 = params.g1;
let g2 = params.g2;
let h = params.h;
self.verify_except_pairings(revealed_msgs, challenge, g1, h)?;
self._verify(revealed_msgs, challenge, pk, params, None)
}

// Verify the randomized signature
if !E::multi_pairing(
[
E::G1Prepared::from(self.A_bar),
E::G1Prepared::from(-(self.B_bar.into_group())),
],
[pk.into().0, g2],
pub fn verify_with_randomized_pairing_checker(
&self,
revealed_msgs: &BTreeMap<usize, E::ScalarField>,
challenge: &E::ScalarField,
pk: impl Into<PreparedPublicKeyG2<E>>,
params: impl Into<PreparedSignatureParams23G1<E>>,
pairing_checker: &mut RandomizedPairingChecker<E>,
) -> Result<(), BBSPlusError> {
self._verify_with_randomized_pairing_checker(
revealed_msgs,
challenge,
pk,
params,
pairing_checker,
None,
)
.is_zero()
{
return Err(BBSPlusError::PairingCheckFailed);
}
Ok(())
}

pub fn verify_with_randomized_pairing_checker(
pub fn verify_partial(
&self,
revealed_msgs: &BTreeMap<usize, E::ScalarField>,
challenge: &E::ScalarField,
pk: impl Into<PreparedPublicKeyG2<E>>,
params: impl Into<PreparedSignatureParams23G1<E>>,
missing_responses: BTreeMap<usize, E::ScalarField>,
) -> Result<(), BBSPlusError> {
self._verify(
revealed_msgs,
challenge,
pk,
params,
Some(missing_responses),
)
}

pub fn verify_partial_with_randomized_pairing_checker(
&self,
revealed_msgs: &BTreeMap<usize, E::ScalarField>,
challenge: &E::ScalarField,
pk: impl Into<PreparedPublicKeyG2<E>>,
params: impl Into<PreparedSignatureParams23G1<E>>,
pairing_checker: &mut RandomizedPairingChecker<E>,
missing_responses: BTreeMap<usize, E::ScalarField>,
) -> Result<(), BBSPlusError> {
let params = params.into();
let g1 = params.g1;
let g2 = params.g2;
let h = params.h;
self.verify_except_pairings(revealed_msgs, challenge, g1, h)?;
pairing_checker.add_sources(&self.A_bar, pk.into().0, &self.B_bar, g2);
Ok(())
self._verify_with_randomized_pairing_checker(
revealed_msgs,
challenge,
pk,
params,
pairing_checker,
Some(missing_responses),
)
}

pub fn get_responses(
&self,
msg_ids: &BTreeSet<usize>,
revealed_msg_ids: &BTreeSet<usize>,
) -> Result<BTreeMap<usize, E::ScalarField>, BBSPlusError> {
let mut resps = BTreeMap::new();
for msg_idx in msg_ids {
resps.insert(
*msg_idx,
*self.get_resp_for_message(*msg_idx, revealed_msg_ids)?,
);
}
Ok(resps)
}

/// For the verifier to independently calculate the challenge
Expand Down Expand Up @@ -335,18 +406,62 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
msg_idx: usize,
revealed_msg_ids: &BTreeSet<usize>,
) -> Result<&E::ScalarField, BBSPlusError> {
// Revealed messages are not part of Schnorr protocol
if revealed_msg_ids.contains(&msg_idx) {
return Err(BBSPlusError::InvalidMsgIdxForResponse(msg_idx));
let adjusted_idx = msg_index_to_schnorr_response_index(msg_idx, revealed_msg_ids)
.ok_or_else(|| BBSPlusError::InvalidMsgIdxForResponse(msg_idx))?;
if let Some(resp) = self.sc_resp_2.as_ref() {
Ok(resp.get_response(adjusted_idx)?)
} else if let Some(resp) = self.sc_partial_resp_2.as_ref() {
Ok(resp.get_response(adjusted_idx)?)
} else {
Err(BBSPlusError::NeedEitherPartialOrCompleteSchnorrResponse)
}
// Adjust message index as the revealed messages are not part of the Schnorr protocol
let mut adjusted_idx = msg_idx;
for i in revealed_msg_ids {
if *i < msg_idx {
adjusted_idx -= 1;
}
}

pub fn _verify(
&self,
revealed_msgs: &BTreeMap<usize, E::ScalarField>,
challenge: &E::ScalarField,
pk: impl Into<PreparedPublicKeyG2<E>>,
params: impl Into<PreparedSignatureParams23G1<E>>,
missing_responses: Option<BTreeMap<usize, E::ScalarField>>,
) -> Result<(), BBSPlusError> {
let params = params.into();
let g1 = params.g1;
let g2 = params.g2;
let h = params.h;
self.verify_except_pairings(revealed_msgs, challenge, g1, h, missing_responses)?;

// Verify the randomized signature
if !E::multi_pairing(
[
E::G1Prepared::from(self.A_bar),
E::G1Prepared::from(-(self.B_bar.into_group())),
],
[pk.into().0, g2],
)
.is_zero()
{
return Err(BBSPlusError::PairingCheckFailed);
}
Ok(self.sc_resp_2.get_response(adjusted_idx)?)
Ok(())
}

pub fn _verify_with_randomized_pairing_checker(
&self,
revealed_msgs: &BTreeMap<usize, E::ScalarField>,
challenge: &E::ScalarField,
pk: impl Into<PreparedPublicKeyG2<E>>,
params: impl Into<PreparedSignatureParams23G1<E>>,
pairing_checker: &mut RandomizedPairingChecker<E>,
missing_responses: Option<BTreeMap<usize, E::ScalarField>>,
) -> Result<(), BBSPlusError> {
let params = params.into();
let g1 = params.g1;
let g2 = params.g2;
let h = params.h;
self.verify_except_pairings(revealed_msgs, challenge, g1, h, missing_responses)?;
pairing_checker.add_sources(&self.A_bar, pk.into().0, &self.B_bar, g2);
Ok(())
}

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

let mut bases_revealed = Vec::with_capacity(1 + revealed_msgs.len());
let mut exponents = Vec::with_capacity(1 + revealed_msgs.len());
bases_revealed.push(g1);
exponents.push(E::ScalarField::one());
let mut bases_revealed = Vec::with_capacity(revealed_msgs.len());
let mut exponents = Vec::with_capacity(revealed_msgs.len());
for i in 0..h.len() {
if revealed_msgs.contains_key(&i) {
let message = revealed_msgs.get(&i).unwrap();
Expand All @@ -382,17 +496,37 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
}
bases_2.push(self.d);
// pr = -g1 + \sum_{i in D}(h_i*{-m_i}) = -(g1 + \sum_{i in D}(h_i*{m_i}))
let pr = -E::G1::msm_unchecked(&bases_revealed, &exponents);
let pr = -E::G1::msm_unchecked(&bases_revealed, &exponents) - g1;
let pr = pr.into_affine();
match self.sc_resp_2.is_valid(&bases_2, &pr, &self.T2, challenge) {
Ok(()) => (),
Err(SchnorrError::InvalidResponse) => {
return Err(BBSPlusError::SecondSchnorrVerificationFailed)
if let Some(resp) = &self.sc_resp_2 {
if missing_responses.is_some() {
return Err(BBSPlusError::MissingResponsesProvidedForFullSchnorrProofVerification);
}
Err(other) => return Err(BBSPlusError::SchnorrError(other)),
return match resp.is_valid(&bases_2, &pr, &self.T2, challenge) {
Ok(()) => Ok(()),
Err(SchnorrError::InvalidResponse) => {
Err(BBSPlusError::SecondSchnorrVerificationFailed)
}
Err(other) => Err(BBSPlusError::SchnorrError(other)),
};
} else if let Some(resp) = &self.sc_partial_resp_2 {
if missing_responses.is_none() {
return Err(BBSPlusError::MissingResponsesNeededForPartialSchnorrProofVerification);
}
let adjusted_missing = msg_index_map_to_schnorr_response_map(
missing_responses.unwrap(),
revealed_msgs.keys(),
);
return match resp.is_valid(&bases_2, &pr, &self.T2, challenge, adjusted_missing) {
Ok(()) => Ok(()),
Err(SchnorrError::InvalidResponse) => {
Err(BBSPlusError::SecondSchnorrVerificationFailed)
}
Err(other) => Err(BBSPlusError::SchnorrError(other)),
};
} else {
Err(BBSPlusError::NeedEitherPartialOrCompleteSchnorrResponse)
}

Ok(())
}

/// Verify the proof except the pairing equations. This is useful when doing several verifications (of this
Expand All @@ -403,11 +537,12 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
challenge: &E::ScalarField,
g1: E::G1Affine,
h: Vec<E::G1Affine>,
missing_responses: Option<BTreeMap<usize, E::ScalarField>>,
) -> Result<(), BBSPlusError> {
if self.A_bar.is_zero() {
return Err(BBSPlusError::ZeroSignature);
}
self.verify_schnorr_proofs(revealed_msgs, challenge, g1, h)
self.verify_schnorr_proofs(revealed_msgs, challenge, g1, h, missing_responses)
}
}

Expand Down
Loading

0 comments on commit afd78fe

Please sign in to comment.