@@ -6,8 +6,8 @@ use crate::issuer::{CredChain, EvenLevelVerkey, OddLevelVerkey};
6
6
use amcl_wrapper:: extension_field_gt:: GT ;
7
7
use amcl_wrapper:: field_elem:: { FieldElement , FieldElementVector } ;
8
8
use amcl_wrapper:: group_elem:: { GroupElement , GroupElementVector } ;
9
- use amcl_wrapper:: group_elem_g1:: { G1Vector , G1 } ;
10
- use amcl_wrapper:: group_elem_g2:: { G2Vector , G2 } ;
9
+ use amcl_wrapper:: group_elem_g1:: { G1LookupTable , G1Vector , G1 } ;
10
+ use amcl_wrapper:: group_elem_g2:: { G2LookupTable , G2Vector , G2 } ;
11
11
use std:: collections:: { HashMap , HashSet } ;
12
12
use std:: ops:: Add ;
13
13
@@ -371,7 +371,6 @@ impl<'a> AttributeToken<'a> {
371
371
FieldElement :: from_msg_hash ( & bytes)
372
372
}
373
373
374
- // TODO: Create a verify_fast that does a single multi-pairing like verify_fast in GrothSig
375
374
pub fn reconstruct_commitment (
376
375
L : usize ,
377
376
comm : & AttributeTokenComm ,
@@ -396,18 +395,21 @@ impl<'a> AttributeToken<'a> {
396
395
let groth2_neg_g2 = -& setup_params_2. g2 ;
397
396
398
397
let challenge_neg = -challenge;
398
+ let challenge_neg_wnaf = challenge_neg. to_wnaf ( 5 ) ;
399
+
400
+ let groth2_g1_table = G1LookupTable :: from ( & setup_params_2. g1 ) ;
401
+ let groth1_g2_table = G2LookupTable :: from ( & setup_params_1. g2 ) ;
402
+ let ipk_table = G2LookupTable :: from ( & ipk. 0 ) ;
403
+
399
404
// g1^-c
400
- let groth2_g1_c = & setup_params_2 . g1 * & challenge_neg ;
405
+ let groth2_g1_c = G1 :: wnaf_mul ( & groth2_g1_table , & challenge_neg_wnaf ) ;
401
406
// g2^-c
402
- let groth1_g2_c = & setup_params_1 . g2 * & challenge_neg ;
407
+ let groth1_g2_c = G2 :: wnaf_mul ( & groth1_g2_table , & challenge_neg_wnaf ) ;
403
408
// ipk^-c
404
- let ipk_c = & ipk. 0 * & challenge_neg;
409
+ let ipk_c = G2 :: wnaf_mul ( & ipk_table, & challenge_neg_wnaf) ;
410
+
405
411
// e(y0, g2)^{-c}
406
- let y0_g2_c = {
407
- // e(y0, g2) can be precomputed
408
- let e_1 = GT :: ate_pairing ( & setup_params_1. y [ 0 ] , & setup_params_1. g2 ) ;
409
- GT :: pow ( & e_1, & challenge_neg)
410
- } ;
412
+ let y0_g2_c = GT :: ate_pairing ( & setup_params_1. y [ 0 ] , & groth1_g2_c) ;
411
413
// e(g1, y0)^{-c} = e(g1^{-c}, y0)
412
414
let g1_y0_c = GT :: ate_pairing ( & groth2_g1_c, & setup_params_2. y [ 0 ] ) ;
413
415
@@ -434,7 +436,7 @@ impl<'a> AttributeToken<'a> {
434
436
// Then e(y[j], ipk)^-c can then be used in a multi-pairing.
435
437
let com_i_s = if i == 1 {
436
438
// e(resp_s_i, r'_i) * e(g1, ipk)^-c
437
- // e(g1, ipk)^-c == e(g1, ipk^-c) => e(resp_s_i, r'_i) * e(g1, ipk^-c)
439
+ // e(g1, ipk)^-c = e(g1, ipk^-c) => e(resp_s_i, r'_i) * e(g1, ipk^-c)
438
440
let e_1 = GT :: ate_2_pairing (
439
441
& resp. odd_level_resp_s [ i / 2 ] ,
440
442
& comm. odd_level_blinded_r [ i / 2 ] ,
@@ -444,12 +446,14 @@ impl<'a> AttributeToken<'a> {
444
446
// e(resp_s_i, r'_i) * ( e(g1, ipk) * e(y0, g2) )^-c
445
447
GT :: mul ( & e_1, & y0_g2_c)
446
448
} else {
449
+ // e(resp_s_i, r'_i) * e(-g1, resp_vk_{i-1})
447
450
let e_1 = GT :: ate_2_pairing (
448
451
& resp. odd_level_resp_s [ i / 2 ] ,
449
452
& comm. odd_level_blinded_r [ i / 2 ] ,
450
453
& groth1_neg_g1,
451
454
& resp. even_level_resp_vk [ ( i / 2 ) - 1 ] ,
452
455
) ;
456
+ // e(resp_s_i, r'_i) * e(-g1, resp_vk_{i-1}) * e(y_0, g2)^-c
453
457
GT :: mul ( & e_1, & y0_g2_c)
454
458
} ;
455
459
comms_s. push ( com_i_s) ;
@@ -521,15 +525,14 @@ impl<'a> AttributeToken<'a> {
521
525
( & setup_params_1. y[ attr_count - 1 ] , & ipk_c) ,
522
526
] )
523
527
} else {
524
- let e_1 = GT :: ate_pairing (
525
- & resp. odd_level_resp_t [ i / 2 ] [ attr_count - 1 ] ,
526
- & comm. odd_level_blinded_r [ i / 2 ] ,
527
- ) ;
528
- let e_2 = GT :: ate_pairing ( & setup_params_1. g1 , & groth1_neg_g2) ;
529
- let e_3 = GT :: pow ( & e_2, & resp. resp_csk ) ;
530
- let e_4 = GT :: mul ( & e_1, & e_3) ;
531
- let e_5 = GT :: ate_pairing ( & setup_params_1. y [ attr_count - 1 ] , & ipk_c) ;
532
- GT :: mul ( & e_4, & e_5)
528
+ GT :: ate_multi_pairing ( vec ! [
529
+ (
530
+ & resp. odd_level_resp_t[ i / 2 ] [ attr_count - 1 ] ,
531
+ & comm. odd_level_blinded_r[ i / 2 ] ,
532
+ ) ,
533
+ ( & ( & setup_params_1. g1 * & resp. resp_csk) , & groth1_neg_g2) ,
534
+ ( & setup_params_1. y[ attr_count - 1 ] , & ipk_c) ,
535
+ ] )
533
536
}
534
537
} else {
535
538
if i != L {
@@ -545,15 +548,17 @@ impl<'a> AttributeToken<'a> {
545
548
( & resp. odd_level_resp_vk[ i / 2 ] , & groth1_neg_g2) ,
546
549
] )
547
550
} else {
548
- let e_1 = GT :: ate_2_pairing (
549
- & resp. odd_level_resp_t [ i / 2 ] [ attr_count - 1 ] ,
550
- & comm. odd_level_blinded_r [ i / 2 ] ,
551
- & ( -& setup_params_1. y [ attr_count - 1 ] ) ,
552
- & resp. even_level_resp_vk [ ( i / 2 ) - 1 ] ,
553
- ) ;
554
- let e_2 = GT :: ate_pairing ( & setup_params_1. g1 , & groth1_neg_g2) ;
555
- let e_3 = GT :: pow ( & e_2, & resp. resp_csk ) ;
556
- GT :: mul ( & e_1, & e_3)
551
+ GT :: ate_multi_pairing ( vec ! [
552
+ (
553
+ & resp. odd_level_resp_t[ i / 2 ] [ attr_count - 1 ] ,
554
+ & comm. odd_level_blinded_r[ i / 2 ] ,
555
+ ) ,
556
+ (
557
+ & ( -& setup_params_1. y[ attr_count - 1 ] ) ,
558
+ & resp. even_level_resp_vk[ ( i / 2 ) - 1 ] ,
559
+ ) ,
560
+ ( & ( & setup_params_1. g1 * & resp. resp_csk) , & groth1_neg_g2) ,
561
+ ] )
557
562
}
558
563
} ;
559
564
com_t. push ( com_i_vk) ;
@@ -639,15 +644,17 @@ impl<'a> AttributeToken<'a> {
639
644
( & groth2_neg_g1, & resp. even_level_resp_vk[ ( i / 2 ) - 1 ] ) ,
640
645
] )
641
646
} else {
642
- let e_1 = GT :: ate_2_pairing (
643
- & comm. even_level_blinded_r [ ( i / 2 ) - 1 ] ,
644
- & resp. even_level_resp_t [ ( i / 2 ) - 1 ] [ attr_count - 1 ] ,
645
- & resp. odd_level_resp_vk [ ( i / 2 ) - 1 ] ,
646
- & ( -& setup_params_2. y [ attr_count - 1 ] ) ,
647
- ) ;
648
- let e_2 = GT :: ate_pairing ( & groth2_neg_g1, & setup_params_2. g2 ) ;
649
- let e_3 = GT :: pow ( & e_2, & resp. resp_csk ) ;
650
- GT :: mul ( & e_1, & e_3)
647
+ GT :: ate_multi_pairing ( vec ! [
648
+ (
649
+ & comm. even_level_blinded_r[ ( i / 2 ) - 1 ] ,
650
+ & resp. even_level_resp_t[ ( i / 2 ) - 1 ] [ attr_count - 1 ] ,
651
+ ) ,
652
+ (
653
+ & resp. odd_level_resp_vk[ ( i / 2 ) - 1 ] ,
654
+ & ( -& setup_params_2. y[ attr_count - 1 ] ) ,
655
+ ) ,
656
+ ( & ( & groth2_neg_g1 * & resp. resp_csk) , & setup_params_2. g2) ,
657
+ ] )
651
658
} ;
652
659
com_t. push ( com_i_vk) ;
653
660
comms_t. push ( com_t) ;
@@ -715,14 +722,13 @@ impl<'a> AttributeToken<'a> {
715
722
716
723
let com_i_s = if i == 1 {
717
724
// e(g1, ri)^{rho_sig*rho_s}
718
- GT :: pow ( pairing_g1_r_i , & ( & rho_sig * & rho_s) )
725
+ pairing_g1_r_i . pow ( & ( & rho_sig * & rho_s) )
719
726
} else {
720
727
// e(g1, ri)^{rho_sig*rho_s} * e(-g1, g2)^{blindings_vk[i-2]}
721
- let e_1 = GT :: pow ( pairing_g1_r_i, & ( & rho_sig * & rho_s) ) ;
722
- let e_2 = GT :: pow (
723
- & precomp_setup. pairing_inv_groth1_g1_g2 ,
724
- & self . blindings_vk [ i - 2 ] ,
725
- ) ;
728
+ let e_1 = pairing_g1_r_i. pow ( & ( & rho_sig * & rho_s) ) ;
729
+ let e_2 = precomp_setup
730
+ . pairing_inv_groth1_g1_g2
731
+ . pow ( & self . blindings_vk [ i - 2 ] ) ;
726
732
GT :: mul ( & e_1, & e_2)
727
733
} ;
728
734
@@ -745,21 +751,20 @@ impl<'a> AttributeToken<'a> {
745
751
746
752
let mut com_i_t = if i == 1 {
747
753
// e(g1, ri)^{rho_sig*rr_t}
748
- GT :: pow ( pairing_g1_r_i , & ( & rho_sig * & rr_t) )
754
+ pairing_g1_r_i . pow ( & ( & rho_sig * & rr_t) )
749
755
} else {
750
756
// e(g1, ri)^{rho_sig*rr_t} * e(-y1_j, g2)^{blindings_vk[i-2]}
751
757
// e(-y1_j, g2) equals e(y1_j, -g2)
752
- let e_1 = GT :: pow ( pairing_g1_r_i, & ( & rho_sig * & rr_t) ) ;
753
- let e_2 = precomp_setup. groth1_neg_y_g2 [ j] . clone ( ) ;
754
- let e_3 = GT :: pow ( & e_2, & self . blindings_vk [ i - 2 ] ) ;
755
- GT :: mul ( & e_1, & e_3)
758
+ let e_1 = pairing_g1_r_i. pow ( & ( & rho_sig * & rr_t) ) ;
759
+ let e_2 = precomp_setup. groth1_neg_y_g2 [ j] . pow ( & self . blindings_vk [ i - 2 ] ) ;
760
+ GT :: mul ( & e_1, & e_2)
756
761
} ;
757
762
758
763
if !revealed[ i - 1 ] . contains ( & j) {
759
764
// Unrevealed attribute
760
765
// e(-g1, g2)^rr_a
761
766
let rr_a = FieldElement :: random ( ) ;
762
- let e = GT :: pow ( & precomp_setup. pairing_inv_groth1_g1_g2 , & rr_a) ;
767
+ let e = precomp_setup. pairing_inv_groth1_g1_g2 . pow ( & rr_a) ;
763
768
// e(g1, ri)^{rho_sig*rr_t} * e(y1_j, g2)^{blindings_vk[i-2]} * e(-g1, g2)^rr_a
764
769
com_i_t = GT :: mul ( & com_i_t, & e) ;
765
770
r_a. push ( rr_a) ;
@@ -776,17 +781,17 @@ impl<'a> AttributeToken<'a> {
776
781
let rr_t = FieldElement :: random ( ) ;
777
782
let mut com_i_vk = {
778
783
// e(g1, ri)^{rho_sig*rr_t} * e(-g1, g2)^rr_a
779
- let e_1 = GT :: pow ( pairing_g1_r_i , & ( & rho_sig * & rr_t) ) ;
780
- let e_2 = GT :: pow ( & precomp_setup. pairing_inv_groth1_g1_g2 , & rho_vk) ;
784
+ let e_1 = pairing_g1_r_i . pow ( & ( & rho_sig * & rr_t) ) ;
785
+ let e_2 = precomp_setup. pairing_inv_groth1_g1_g2 . pow ( & rho_vk) ;
781
786
GT :: mul ( & e_1, & e_2)
782
787
} ;
783
788
if i != 1 {
784
789
// Different from paper here, paper uses e(y1_j, g2) but e(-y1_j, g2) should be used and e(-y1_j, g2) equals e(y1_j, -g2)
785
790
// e(y1_j, -g2)^{blindings_vk[i-2]}
786
- let e_1 = precomp_setup. groth1_neg_y_g2 [ link. attribute_count ( ) - 1 ] . clone ( ) ;
787
- let e_2 = GT :: pow ( & e_1 , & self . blindings_vk [ i - 2 ] ) ;
791
+ let e = precomp_setup. groth1_neg_y_g2 [ link. attribute_count ( ) - 1 ]
792
+ . pow ( & self . blindings_vk [ i - 2 ] ) ;
788
793
// e(g1, ri)^{rho_sig*rr_t} * e(-g1, g2)^rr_a * e(y1_j, g2)^{blindings_vk[i-2]}
789
- com_i_vk = GT :: mul ( & com_i_vk, & e_2 ) ;
794
+ com_i_vk = GT :: mul ( & com_i_vk, & e ) ;
790
795
}
791
796
com_t. push ( com_i_vk) ;
792
797
r_t. push ( rr_t) ;
@@ -804,11 +809,10 @@ impl<'a> AttributeToken<'a> {
804
809
let pairing_r_i_g2 = & precomp_chain. pairing_g_r [ i - 1 ] ;
805
810
806
811
// e(ri, g2)^{rho_sig*rho_s} * e(-g1, g2)^{blindings_vk[i-2]}
807
- let e_1 = GT :: pow ( pairing_r_i_g2, & ( & rho_sig * & rho_s) ) ;
808
- let e_2 = GT :: pow (
809
- & precomp_setup. pairing_inv_groth2_g1_g2 ,
810
- & self . blindings_vk [ i - 2 ] ,
811
- ) ;
812
+ let e_1 = pairing_r_i_g2. pow ( & ( & rho_sig * & rho_s) ) ;
813
+ let e_2 = precomp_setup
814
+ . pairing_inv_groth2_g1_g2
815
+ . pow ( & self . blindings_vk [ i - 2 ] ) ;
812
816
let com_i_s = GT :: mul ( & e_1, & e_2) ;
813
817
814
818
if revealed[ i - 1 ] . len ( ) > self . setup_params_2 . y . len ( ) {
@@ -830,10 +834,9 @@ impl<'a> AttributeToken<'a> {
830
834
831
835
// e(ri, g2)^{rho_sig*rr_t} * e(g1, -y2_j)^{blindings_vk[i-2]}.
832
836
// e(g1, -y2_j) equals e(-g1, y2_j)
833
- let e_1 = GT :: pow ( pairing_r_i_g2, & ( & rho_sig * & rr_t) ) ;
834
- let e_2 = precomp_setup. groth2_neg_g1_y [ j] . clone ( ) ;
835
- let e_3 = GT :: pow ( & e_2, & self . blindings_vk [ i - 2 ] ) ;
836
- let mut com_i_t = GT :: mul ( & e_1, & e_3) ;
837
+ let e_1 = pairing_r_i_g2. pow ( & ( & rho_sig * & rr_t) ) ;
838
+ let e_2 = precomp_setup. groth2_neg_g1_y [ j] . pow ( & self . blindings_vk [ i - 2 ] ) ;
839
+ let mut com_i_t = GT :: mul ( & e_1, & e_2) ;
837
840
838
841
if !revealed[ i - 1 ] . contains ( & j) {
839
842
// Unrevealed attribute
@@ -858,9 +861,9 @@ impl<'a> AttributeToken<'a> {
858
861
// In above, replace e(g1, -y2_j)^{blindings_vk[i-2]} with e(-g1, y2_j)^{blindings_vk[i-2]}
859
862
let e_1 = GT :: pow ( pairing_r_i_g2, & ( & rho_sig * & rr_t) ) ;
860
863
let e_2 = GT :: pow ( & precomp_setup. pairing_inv_groth2_g1_g2 , & rho_vk) ;
861
- let e_3 = precomp_setup. groth2_neg_g1_y [ link. attribute_count ( ) - 1 ] . clone ( ) ;
862
- let e_4 = GT :: pow ( & e_3 , & self . blindings_vk [ i - 2 ] ) ;
863
- let com_i_vk = GT :: mul ( & GT :: mul ( & e_1, & e_2) , & e_4 ) ;
864
+ let e_3 = precomp_setup. groth2_neg_g1_y [ link. attribute_count ( ) - 1 ]
865
+ . pow ( & self . blindings_vk [ i - 2 ] ) ;
866
+ let com_i_vk = GT :: mul ( & GT :: mul ( & e_1, & e_2) , & e_3 ) ;
864
867
865
868
com_t. push ( com_i_vk) ;
866
869
r_t. push ( rr_t) ;
@@ -931,9 +934,9 @@ impl<'a> AttributeToken<'a> {
931
934
// ipk^-c
932
935
let ipk_c = & ipk. 0 * & challenge_neg;
933
936
// e(y0, g2)^{-c}
934
- let y0_g2_c = GT :: pow ( & precomputed. groth1_y0_g2 , & challenge_neg) ;
937
+ let y0_g2_c = precomputed. groth1_y0_g2 . pow ( & challenge_neg) ;
935
938
// e(g1, y0)^{-c}
936
- let g1_y0_c = GT :: pow ( & precomputed. groth2_g1_y0 , & challenge_neg) ;
939
+ let g1_y0_c = & precomputed. groth2_g1_y0 . pow ( & challenge_neg) ;
937
940
938
941
for i in 1 ..=L {
939
942
if i % 2 == 1 {
@@ -2352,28 +2355,58 @@ mod tests {
2352
2355
2353
2356
let mut morphed_commitment = com_1. clone ( ) ;
2354
2357
// Adding an element of comms_s to increase its size
2355
- morphed_commitment. comms_s . push ( morphed_commitment. comms_s [ 0 ] . clone ( ) ) ;
2358
+ morphed_commitment
2359
+ . comms_s
2360
+ . push ( morphed_commitment. comms_s [ 0 ] . clone ( ) ) ;
2356
2361
assert ! ( at_1
2357
- . response( & morphed_commitment, & l_1_issuer_sk. 0 , & c_1, vec![ ] , vec![ & l_1_issuer_vk] ) . is_err( ) ) ;
2362
+ . response(
2363
+ & morphed_commitment,
2364
+ & l_1_issuer_sk. 0 ,
2365
+ & c_1,
2366
+ vec![ ] ,
2367
+ vec![ & l_1_issuer_vk]
2368
+ )
2369
+ . is_err( ) ) ;
2358
2370
// Remove the added element
2359
2371
morphed_commitment. comms_s . pop ( ) . unwrap ( ) ;
2360
2372
2361
2373
// Adding an element of comms_t to increase its size
2362
2374
morphed_commitment. comms_t . push ( vec ! [ ] ) ;
2363
2375
assert ! ( at_1
2364
- . response( & morphed_commitment, & l_1_issuer_sk. 0 , & c_1, vec![ ] , vec![ & l_1_issuer_vk] ) . is_err( ) ) ;
2376
+ . response(
2377
+ & morphed_commitment,
2378
+ & l_1_issuer_sk. 0 ,
2379
+ & c_1,
2380
+ vec![ ] ,
2381
+ vec![ & l_1_issuer_vk]
2382
+ )
2383
+ . is_err( ) ) ;
2365
2384
// Remove the added element
2366
2385
morphed_commitment. comms_t . pop ( ) . unwrap ( ) ;
2367
2386
2368
2387
// Decrease size of comms_s
2369
2388
morphed_commitment. comms_s . pop ( ) . unwrap ( ) ;
2370
2389
assert ! ( at_1
2371
- . response( & morphed_commitment, & l_1_issuer_sk. 0 , & c_1, vec![ ] , vec![ & l_1_issuer_vk] ) . is_err( ) ) ;
2390
+ . response(
2391
+ & morphed_commitment,
2392
+ & l_1_issuer_sk. 0 ,
2393
+ & c_1,
2394
+ vec![ ] ,
2395
+ vec![ & l_1_issuer_vk]
2396
+ )
2397
+ . is_err( ) ) ;
2372
2398
2373
2399
// Decrease size of comms_t
2374
2400
morphed_commitment. comms_t . pop ( ) . unwrap ( ) ;
2375
2401
assert ! ( at_1
2376
- . response( & morphed_commitment, & l_1_issuer_sk. 0 , & c_1, vec![ ] , vec![ & l_1_issuer_vk] ) . is_err( ) ) ;
2402
+ . response(
2403
+ & morphed_commitment,
2404
+ & l_1_issuer_sk. 0 ,
2405
+ & c_1,
2406
+ vec![ ] ,
2407
+ vec![ & l_1_issuer_vk]
2408
+ )
2409
+ . is_err( ) ) ;
2377
2410
2378
2411
let resp_1 = at_1
2379
2412
. response ( & com_1, & l_1_issuer_sk. 0 , & c_1, vec ! [ ] , vec ! [ & l_1_issuer_vk] )
0 commit comments