@@ -71,8 +71,10 @@ use ark_std::{
7171 vec:: Vec ,
7272 One , UniformRand ,
7373} ;
74+ use dock_crypto_utils:: extend_some:: ExtendSome ;
7475use dock_crypto_utils:: randomized_pairing_check:: RandomizedPairingChecker ;
75- use dock_crypto_utils:: serde_utils:: * ;
76+ use dock_crypto_utils:: { misc:: rand, serde_utils:: * } ;
77+ use itertools:: multiunzip;
7678use schnorr_pok:: { error:: SchnorrError , SchnorrCommitment , SchnorrResponse } ;
7779use serde:: { Deserialize , Serialize } ;
7880use serde_with:: serde_as;
@@ -131,58 +133,57 @@ pub struct PoKOfSignatureG1Proof<E: Pairing> {
131133 pub sc_resp_2 : SchnorrResponse < E :: G1Affine > ,
132134}
133135
136+ /// Each message can be either randomly blinded, unblinded, or blinded using supplied blinding.
137+ /// By default, a message is blinded with random blinding.
138+ pub enum MessageOrBlinding < ' a , P : PrimeField > {
139+ /// Message will be blinded using random blinding.
140+ BlindMessageRandomly ( & ' a P ) ,
141+ /// Message will be revealed, and thus won't be included in PoK.
142+ RevealMessage ( & ' a P ) ,
143+ /// Message will be blinded using the supplied blinding.
144+ BlindMessageWithConcreteBlinding { message : & ' a P , blinding : P } ,
145+ }
146+
134147impl < E : Pairing > PoKOfSignatureG1Protocol < E > {
135148 /// Initiate the protocol, i.e. pre-challenge phase. This will generate the randomized signature and execute
136- /// the commit-to-randomness step (Step 1) of both Schnorr protocols. Accepts the indices of the
137- /// multi-message which are revealed to the verifier and thus their knowledge is not proven.
138- /// Accepts blindings (randomness) to be used for any messages in the multi-message. This is useful
139- /// when some messages need to be proven to be the same as they will generate the same response (step 3 in
140- /// Schnorr protocol). If extra blindings are passed, or passed for revealed messages, they are ignored.
141- /// eg. If the multi-message is `[m_0, m_1, m_2, m_3, m_4]` and the user provides blindings for messages
142- /// `m_0` and `m_2` and revealing messages `m_1`, `m_3` and `m_4`, `blindings` is `(0 -> m_0), (2 -> m_2)`
143- /// and `revealed_msg_indices` is `(1 -> m_1), (3 -> m_3), (4 -> m_4)`
144- pub fn init < R : RngCore > (
149+ /// the commit-to-randomness step (Step 1) of both Schnorr protocols.
150+ /// Accepts an iterator of messages. Each message can be either randomly blinded, revealed, or blinded using supplied blinding.
151+ pub fn init < ' a , MBI , R : RngCore > (
145152 rng : & mut R ,
146153 signature : & SignatureG1 < E > ,
147154 params : & SignatureParamsG1 < E > ,
148- messages : & [ E :: ScalarField ] ,
149- mut blindings : BTreeMap < usize , E :: ScalarField > ,
150- revealed_msg_indices : BTreeSet < usize > ,
151- ) -> Result < Self , BBSPlusError > {
155+ messages_and_blindings : MBI ,
156+ ) -> Result < Self , BBSPlusError >
157+ where
158+ MBI : IntoIterator < Item = MessageOrBlinding < ' a , E :: ScalarField > > ,
159+ {
160+ let ( messages, ExtendSome :: < Vec < _ > > ( indexed_blindings) ) : ( Vec < _ > , _ ) =
161+ messages_and_blindings
162+ . into_iter ( )
163+ . enumerate ( )
164+ . map ( |( idx, msg_or_blinding) | match msg_or_blinding {
165+ MessageOrBlinding :: BlindMessageRandomly ( message) => {
166+ ( message, ( idx, rand ( rng) ) . into ( ) )
167+ }
168+ MessageOrBlinding :: BlindMessageWithConcreteBlinding { message, blinding } => {
169+ ( message, ( idx, blinding) . into ( ) )
170+ }
171+ MessageOrBlinding :: RevealMessage ( message) => ( message, None ) ,
172+ } )
173+ . unzip ( ) ;
152174 if messages. len ( ) != params. supported_message_count ( ) {
153- return Err ( BBSPlusError :: MessageCountIncompatibleWithSigParams (
175+ Err ( BBSPlusError :: MessageCountIncompatibleWithSigParams (
154176 messages. len ( ) ,
155177 params. supported_message_count ( ) ,
156- ) ) ;
157- }
158-
159- // No message index should be >= max messages
160- for idx in & revealed_msg_indices {
161- if * idx >= messages. len ( ) {
162- return Err ( BBSPlusError :: InvalidMessageIdx ( * idx) ) ;
163- }
164- }
165-
166- // Generate any blindings that are not explicitly passed. At the end of the loop, we should have
167- // a blinding for every message whose knowledge is to be proven
168- for i in 0 ..messages. len ( ) {
169- if !revealed_msg_indices. contains ( & i) && !blindings. contains_key ( & i) {
170- blindings. insert ( i, E :: ScalarField :: rand ( rng) ) ;
171- }
178+ ) ) ?
172179 }
173180
174181 let r1 = E :: ScalarField :: rand ( rng) ;
175182 let r2 = E :: ScalarField :: rand ( rng) ;
176183 let r3 = r1. inverse ( ) . ok_or ( BBSPlusError :: CannotInvert0 ) ?;
177184
178185 // b = (e+x) * A = g1 + h_0*s + sum(h_i*m_i) for all i in I
179- let b = params. b (
180- messages
181- . iter ( )
182- . enumerate ( )
183- . collect :: < BTreeMap < usize , & E :: ScalarField > > ( ) ,
184- & signature. s ,
185- ) ?;
186+ let b = params. b ( messages. iter ( ) . enumerate ( ) , & signature. s ) ?;
186187
187188 // A' = A * r1
188189 let A_prime = signature. A . mul_bigint ( r1. into_bigint ( ) ) ;
@@ -224,31 +225,23 @@ impl<E: Pairing> PoKOfSignatureG1Protocol<E> {
224225 // Knowledge of all unrevealed messages `m_j` need to be proven in addition to knowledge of `-r3` and `s'`. Thus
225226 // all `m_j`, `-r3` and `s'` are the witnesses, while all `h_j`, `d`, `h_0` and `-g1 + \sum_{i \in D}(h_i*{-m_i})` is the instance.
226227
227- let mut bases_2 = Vec :: with_capacity ( 2 + blindings. len ( ) ) ;
228- let mut randomness_2 = Vec :: with_capacity ( 2 + blindings. len ( ) ) ;
229- let mut wits_2 = Vec :: with_capacity ( 2 + blindings. len ( ) ) ;
230- bases_2. push ( d_affine) ;
231- randomness_2. push ( E :: ScalarField :: rand ( rng) ) ;
232- wits_2. push ( -r3) ;
233- bases_2. push ( h_0) ;
234- randomness_2. push ( E :: ScalarField :: rand ( rng) ) ;
235- wits_2. push ( s_prime) ;
236-
237- // Capture all unrevealed messages `m_j` and corresponding `h_j`
238- for i in 0 ..messages. len ( ) {
239- if !revealed_msg_indices. contains ( & i) {
240- bases_2. push ( params. h [ i] ) ;
241- randomness_2. push ( blindings. remove ( & i) . unwrap ( ) ) ;
242- wits_2. push ( messages[ i] ) ;
243- }
244- }
228+ let h_blinding_message = indexed_blindings
229+ . into_iter ( )
230+ . map ( |( idx, blinding) | ( params. h [ idx] , blinding, messages[ idx] ) ) ;
231+
232+ let ( bases_2, randomness_2, wits_2) : ( Vec < _ > , Vec < _ > , Vec < _ > ) = multiunzip (
233+ [ ( d_affine, rand ( rng) , -r3) , ( h_0, rand ( rng) , s_prime) ]
234+ . into_iter ( )
235+ . chain ( h_blinding_message) ,
236+ ) ;
245237
246238 // Commit to randomness, i.e. `bases_2[0]*randomness_2[0] + bases_2[1]*randomness_2[1] + .... bases_2[j]*randomness_2[j]`
247239 let sc_comm_2 = SchnorrCommitment :: new ( & bases_2, randomness_2) ;
240+
248241 Ok ( Self {
249242 A_prime : A_prime_affine ,
250243 A_bar : A_bar . into_affine ( ) ,
251- d : bases_2. remove ( 0 ) ,
244+ d : bases_2[ 0 ] ,
252245 sc_comm_1,
253246 sc_wits_1 : wits_1,
254247 sc_comm_2,
@@ -588,9 +581,13 @@ mod tests {
588581 & mut rng,
589582 & sig,
590583 & params,
591- messages. as_slice ( ) ,
592- BTreeMap :: new ( ) ,
593- revealed_indices. clone ( ) ,
584+ messages. iter ( ) . enumerate ( ) . map ( |( idx, msg) | {
585+ if revealed_indices. contains ( & idx) {
586+ MessageOrBlinding :: RevealMessage ( msg)
587+ } else {
588+ MessageOrBlinding :: BlindMessageRandomly ( msg)
589+ }
590+ } ) ,
594591 )
595592 . unwrap ( ) ;
596593 proof_create_duration += start. elapsed ( ) ;
@@ -720,18 +717,32 @@ mod tests {
720717 & mut rng,
721718 & sig_1,
722719 & params_1,
723- & messages_1,
724- blindings_1,
725- BTreeSet :: new ( ) ,
720+ messages_1. iter ( ) . enumerate ( ) . map ( |( idx, message) | {
721+ if let Some ( blinding) = blindings_1. remove ( & idx) {
722+ MessageOrBlinding :: BlindMessageWithConcreteBlinding {
723+ message,
724+ blinding : blinding,
725+ }
726+ } else {
727+ MessageOrBlinding :: BlindMessageRandomly ( message)
728+ }
729+ } ) ,
726730 )
727731 . unwrap ( ) ;
728732 let pok_2 = PoKOfSignatureG1Protocol :: init (
729733 & mut rng,
730734 & sig_2,
731735 & params_2,
732- & messages_2,
733- blindings_2,
734- BTreeSet :: new ( ) ,
736+ messages_2. iter ( ) . enumerate ( ) . map ( |( idx, message) | {
737+ if let Some ( blinding) = blindings_2. remove ( & idx) {
738+ MessageOrBlinding :: BlindMessageWithConcreteBlinding {
739+ message,
740+ blinding : blinding,
741+ }
742+ } else {
743+ MessageOrBlinding :: BlindMessageRandomly ( message)
744+ }
745+ } ) ,
735746 )
736747 . unwrap ( ) ;
737748
@@ -802,9 +813,13 @@ mod tests {
802813 & mut rng,
803814 & sig,
804815 & params,
805- messages. as_slice ( ) ,
806- BTreeMap :: new ( ) ,
807- revealed_indices_1. clone ( ) ,
816+ messages. iter ( ) . enumerate ( ) . map ( |( idx, msg) | {
817+ if revealed_indices_1. contains ( & idx) {
818+ MessageOrBlinding :: RevealMessage ( msg)
819+ } else {
820+ MessageOrBlinding :: BlindMessageRandomly ( msg)
821+ }
822+ } ) ,
808823 )
809824 . unwrap ( ) ;
810825 let proof_1 = pok_1. gen_proof ( & challenge) . unwrap ( ) ;
@@ -826,9 +841,13 @@ mod tests {
826841 & mut rng,
827842 & sig,
828843 & params,
829- messages. as_slice ( ) ,
830- BTreeMap :: new ( ) ,
831- revealed_indices_2. clone ( ) ,
844+ messages. iter ( ) . enumerate ( ) . map ( |( idx, msg) | {
845+ if revealed_indices_2. contains ( & idx) {
846+ MessageOrBlinding :: RevealMessage ( msg)
847+ } else {
848+ MessageOrBlinding :: BlindMessageRandomly ( msg)
849+ }
850+ } ) ,
832851 )
833852 . unwrap ( ) ;
834853 let proof_2 = pok_2. gen_proof ( & challenge) . unwrap ( ) ;
@@ -871,9 +890,13 @@ mod tests {
871890 & mut rng,
872891 & sig,
873892 & params,
874- messages. as_slice ( ) ,
875- BTreeMap :: new ( ) ,
876- revealed_indices_3. clone ( ) ,
893+ messages. iter ( ) . enumerate ( ) . map ( |( idx, msg) | {
894+ if revealed_indices_3. contains ( & idx) {
895+ MessageOrBlinding :: RevealMessage ( msg)
896+ } else {
897+ MessageOrBlinding :: BlindMessageRandomly ( msg)
898+ }
899+ } ) ,
877900 )
878901 . unwrap ( ) ;
879902 let proof_3 = pok_3. gen_proof ( & challenge) . unwrap ( ) ;
@@ -920,9 +943,13 @@ mod tests {
920943 & mut rng,
921944 & sig,
922945 & params,
923- messages. as_slice ( ) ,
924- BTreeMap :: new ( ) ,
925- revealed_indices. clone ( ) ,
946+ messages. iter ( ) . enumerate ( ) . map ( |( idx, msg) | {
947+ if revealed_indices. contains ( & idx) {
948+ MessageOrBlinding :: RevealMessage ( msg)
949+ } else {
950+ MessageOrBlinding :: BlindMessageRandomly ( msg)
951+ }
952+ } ) ,
926953 )
927954 . unwrap ( ) ;
928955 let proof = pok. gen_proof ( & challenge) . unwrap ( ) ;
@@ -978,9 +1005,7 @@ mod tests {
9781005 & mut rng,
9791006 & sigs[ i] ,
9801007 & params,
981- & msgs[ i] ,
982- BTreeMap :: new ( ) ,
983- BTreeSet :: new ( ) ,
1008+ msgs[ i] . iter ( ) . map ( MessageOrBlinding :: BlindMessageRandomly ) ,
9841009 )
9851010 . unwrap ( ) ;
9861011 pok. challenge_contribution ( & BTreeMap :: new ( ) , & params, & mut chal_bytes_prover)
0 commit comments