@@ -30,19 +30,24 @@ use ark_std::{
30
30
io:: Write ,
31
31
rand:: RngCore ,
32
32
vec:: Vec ,
33
- One , UniformRand ,
33
+ UniformRand ,
34
34
} ;
35
35
use core:: mem;
36
36
use dock_crypto_utils:: {
37
37
misc:: rand,
38
38
randomized_pairing_check:: RandomizedPairingChecker ,
39
39
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
+ } ,
41
45
} ;
42
46
use itertools:: multiunzip;
43
47
use schnorr_pok:: {
44
48
discrete_log:: { PokTwoDiscreteLogs , PokTwoDiscreteLogsProtocol } ,
45
49
error:: SchnorrError ,
50
+ partial:: PartialSchnorrResponse ,
46
51
SchnorrCommitment , SchnorrResponse ,
47
52
} ;
48
53
use serde:: { Deserialize , Serialize } ;
@@ -99,7 +104,8 @@ pub struct PoKOfSignature23G1Proof<E: Pairing> {
99
104
/// 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`
100
105
#[ serde_as( as = "ArkObjectBytes" ) ]
101
106
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 > > ,
103
109
}
104
110
105
111
impl < E : Pairing > PoKOfSignature23G1Protocol < E > {
@@ -228,7 +234,38 @@ impl<E: Pairing> PoKOfSignature23G1Protocol<E> {
228
234
d : self . d ,
229
235
sc_resp_1,
230
236
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) ,
232
269
} )
233
270
}
234
271
@@ -271,42 +308,76 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
271
308
pk : impl Into < PreparedPublicKeyG2 < E > > ,
272
309
params : impl Into < PreparedSignatureParams23G1 < E > > ,
273
310
) -> 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
+ }
279
313
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 ,
287
329
)
288
- . is_zero ( )
289
- {
290
- return Err ( BBSPlusError :: PairingCheckFailed ) ;
291
- }
292
- Ok ( ( ) )
293
330
}
294
331
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 (
296
350
& self ,
297
351
revealed_msgs : & BTreeMap < usize , E :: ScalarField > ,
298
352
challenge : & E :: ScalarField ,
299
353
pk : impl Into < PreparedPublicKeyG2 < E > > ,
300
354
params : impl Into < PreparedSignatureParams23G1 < E > > ,
301
355
pairing_checker : & mut RandomizedPairingChecker < E > ,
356
+ missing_responses : BTreeMap < usize , E :: ScalarField > ,
302
357
) -> 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)
310
381
}
311
382
312
383
/// For the verifier to independently calculate the challenge
@@ -335,18 +406,62 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
335
406
msg_idx : usize ,
336
407
revealed_msg_ids : & BTreeSet < usize > ,
337
408
) -> 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 )
341
417
}
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 ) ;
348
445
}
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 ( ( ) )
350
465
}
351
466
352
467
pub fn verify_schnorr_proofs (
@@ -355,6 +470,7 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
355
470
challenge : & E :: ScalarField ,
356
471
g1 : E :: G1Affine ,
357
472
h : Vec < E :: G1Affine > ,
473
+ missing_responses : Option < BTreeMap < usize , E :: ScalarField > > ,
358
474
) -> Result < ( ) , BBSPlusError > {
359
475
// Verify the 1st Schnorr proof
360
476
if !self
@@ -367,10 +483,8 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
367
483
// Verify the 2nd Schnorr proof
368
484
let mut bases_2 = Vec :: with_capacity ( 1 + h. len ( ) - revealed_msgs. len ( ) ) ;
369
485
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 ( ) ) ;
374
488
for i in 0 ..h. len ( ) {
375
489
if revealed_msgs. contains_key ( & i) {
376
490
let message = revealed_msgs. get ( & i) . unwrap ( ) ;
@@ -382,17 +496,37 @@ impl<E: Pairing> PoKOfSignature23G1Proof<E> {
382
496
}
383
497
bases_2. push ( self . d ) ;
384
498
// 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 ;
386
500
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 ) ;
391
504
}
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 )
393
529
}
394
-
395
- Ok ( ( ) )
396
530
}
397
531
398
532
/// 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> {
403
537
challenge : & E :: ScalarField ,
404
538
g1 : E :: G1Affine ,
405
539
h : Vec < E :: G1Affine > ,
540
+ missing_responses : Option < BTreeMap < usize , E :: ScalarField > > ,
406
541
) -> Result < ( ) , BBSPlusError > {
407
542
if self . A_bar . is_zero ( ) {
408
543
return Err ( BBSPlusError :: ZeroSignature ) ;
409
544
}
410
- self . verify_schnorr_proofs ( revealed_msgs, challenge, g1, h)
545
+ self . verify_schnorr_proofs ( revealed_msgs, challenge, g1, h, missing_responses )
411
546
}
412
547
}
413
548
0 commit comments