charm-crypto-framework 0.61.1__cp313-cp313-macosx_10_13_universal2.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- charm/__init__.py +5 -0
- charm/adapters/__init__.py +0 -0
- charm/adapters/abenc_adapt_hybrid.py +90 -0
- charm/adapters/dabenc_adapt_hybrid.py +145 -0
- charm/adapters/ibenc_adapt_hybrid.py +72 -0
- charm/adapters/ibenc_adapt_identityhash.py +80 -0
- charm/adapters/kpabenc_adapt_hybrid.py +91 -0
- charm/adapters/pkenc_adapt_bchk05.py +121 -0
- charm/adapters/pkenc_adapt_chk04.py +91 -0
- charm/adapters/pkenc_adapt_hybrid.py +98 -0
- charm/adapters/pksig_adapt_naor01.py +89 -0
- charm/config.py +7 -0
- charm/core/__init__.py +0 -0
- charm/core/benchmark/benchmark_util.c +353 -0
- charm/core/benchmark/benchmark_util.h +61 -0
- charm/core/benchmark/benchmarkmodule.c +476 -0
- charm/core/benchmark/benchmarkmodule.h +162 -0
- charm/core/benchmark.cpython-313-darwin.so +0 -0
- charm/core/crypto/AES/AES.c +1464 -0
- charm/core/crypto/AES.cpython-313-darwin.so +0 -0
- charm/core/crypto/DES/DES.c +113 -0
- charm/core/crypto/DES.cpython-313-darwin.so +0 -0
- charm/core/crypto/DES3/DES3.c +26 -0
- charm/core/crypto/DES3.cpython-313-darwin.so +0 -0
- charm/core/crypto/__init__.py +0 -0
- charm/core/crypto/cryptobase/XOR.c +80 -0
- charm/core/crypto/cryptobase/_counter.c +496 -0
- charm/core/crypto/cryptobase/_counter.h +54 -0
- charm/core/crypto/cryptobase/block_template.c +900 -0
- charm/core/crypto/cryptobase/block_template.h +69 -0
- charm/core/crypto/cryptobase/cryptobasemodule.c +220 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt.h +90 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_argchk.h +44 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_cfg.h +186 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_cipher.h +941 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_custom.h +556 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_des.c +1912 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_hash.h +407 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_mac.h +496 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_macros.h +435 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_math.h +534 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_misc.h +103 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_pk.h +653 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_pkcs.h +90 -0
- charm/core/crypto/cryptobase/libtom/tomcrypt_prng.h +199 -0
- charm/core/crypto/cryptobase/stream_template.c +271 -0
- charm/core/crypto/cryptobase/strxor.c +229 -0
- charm/core/crypto/cryptobase.cpython-313-darwin.so +0 -0
- charm/core/engine/__init__.py +5 -0
- charm/core/engine/protocol.py +293 -0
- charm/core/engine/util.py +174 -0
- charm/core/math/__init__.py +0 -0
- charm/core/math/elliptic_curve/ecmodule.c +1986 -0
- charm/core/math/elliptic_curve/ecmodule.h +230 -0
- charm/core/math/elliptic_curve.cpython-313-darwin.so +0 -0
- charm/core/math/elliptic_curve.pyi +63 -0
- charm/core/math/integer/integermodule.c +2539 -0
- charm/core/math/integer/integermodule.h +145 -0
- charm/core/math/integer.cpython-313-darwin.so +0 -0
- charm/core/math/integer.pyi +76 -0
- charm/core/math/pairing/miracl/miracl_config.h +37 -0
- charm/core/math/pairing/miracl/miracl_interface.h +118 -0
- charm/core/math/pairing/miracl/miracl_interface2.h +126 -0
- charm/core/math/pairing/miracl/pairingmodule2.c +2094 -0
- charm/core/math/pairing/miracl/pairingmodule2.h +307 -0
- charm/core/math/pairing/pairingmodule.c +2230 -0
- charm/core/math/pairing/pairingmodule.h +241 -0
- charm/core/math/pairing/relic/pairingmodule3.c +1853 -0
- charm/core/math/pairing/relic/pairingmodule3.h +233 -0
- charm/core/math/pairing/relic/relic_interface.c +1337 -0
- charm/core/math/pairing/relic/relic_interface.h +217 -0
- charm/core/math/pairing/relic/test_relic.c +171 -0
- charm/core/math/pairing.cpython-313-darwin.so +0 -0
- charm/core/math/pairing.pyi +69 -0
- charm/core/utilities/base64.c +248 -0
- charm/core/utilities/base64.h +15 -0
- charm/schemes/__init__.py +0 -0
- charm/schemes/abenc/__init__.py +0 -0
- charm/schemes/abenc/abenc_accountability_jyjxgd20.py +647 -0
- charm/schemes/abenc/abenc_bsw07.py +146 -0
- charm/schemes/abenc/abenc_ca_cpabe_ar17.py +684 -0
- charm/schemes/abenc/abenc_dacmacs_yj14.py +298 -0
- charm/schemes/abenc/abenc_lsw08.py +159 -0
- charm/schemes/abenc/abenc_maabe_rw15.py +236 -0
- charm/schemes/abenc/abenc_maabe_yj14.py +297 -0
- charm/schemes/abenc/abenc_tbpre_lww14.py +309 -0
- charm/schemes/abenc/abenc_unmcpabe_yahk14.py +223 -0
- charm/schemes/abenc/abenc_waters09.py +144 -0
- charm/schemes/abenc/abenc_yct14.py +208 -0
- charm/schemes/abenc/abenc_yllc15.py +178 -0
- charm/schemes/abenc/ac17.py +248 -0
- charm/schemes/abenc/bsw07.py +141 -0
- charm/schemes/abenc/cgw15.py +277 -0
- charm/schemes/abenc/dabe_aw11.py +204 -0
- charm/schemes/abenc/dfa_fe12.py +144 -0
- charm/schemes/abenc/pk_hve08.py +179 -0
- charm/schemes/abenc/waters11.py +143 -0
- charm/schemes/aggrsign_MuSig.py +150 -0
- charm/schemes/aggrsign_bls.py +267 -0
- charm/schemes/blindsig_ps16.py +654 -0
- charm/schemes/chamhash_adm05.py +113 -0
- charm/schemes/chamhash_rsa_hw09.py +100 -0
- charm/schemes/commit/__init__.py +0 -0
- charm/schemes/commit/commit_gs08.py +77 -0
- charm/schemes/commit/commit_pedersen92.py +53 -0
- charm/schemes/encap_bchk05.py +62 -0
- charm/schemes/grpsig/__init__.py +0 -0
- charm/schemes/grpsig/groupsig_bgls04.py +114 -0
- charm/schemes/grpsig/groupsig_bgls04_var.py +115 -0
- charm/schemes/hibenc/__init__.py +0 -0
- charm/schemes/hibenc/hibenc_bb04.py +105 -0
- charm/schemes/hibenc/hibenc_lew11.py +193 -0
- charm/schemes/ibenc/__init__.py +0 -0
- charm/schemes/ibenc/clpkc_rp03.py +119 -0
- charm/schemes/ibenc/ibenc_CW13_z.py +168 -0
- charm/schemes/ibenc/ibenc_bb03.py +94 -0
- charm/schemes/ibenc/ibenc_bf01.py +121 -0
- charm/schemes/ibenc/ibenc_ckrs09.py +120 -0
- charm/schemes/ibenc/ibenc_cllww12_z.py +172 -0
- charm/schemes/ibenc/ibenc_lsw08.py +120 -0
- charm/schemes/ibenc/ibenc_sw05.py +238 -0
- charm/schemes/ibenc/ibenc_waters05.py +144 -0
- charm/schemes/ibenc/ibenc_waters05_z.py +164 -0
- charm/schemes/ibenc/ibenc_waters09.py +107 -0
- charm/schemes/ibenc/ibenc_waters09_z.py +147 -0
- charm/schemes/joye_scheme.py +106 -0
- charm/schemes/lem_scheme.py +207 -0
- charm/schemes/pk_fre_ccv11.py +107 -0
- charm/schemes/pk_vrf.py +127 -0
- charm/schemes/pkenc/__init__.py +0 -0
- charm/schemes/pkenc/pkenc_cs98.py +108 -0
- charm/schemes/pkenc/pkenc_elgamal85.py +122 -0
- charm/schemes/pkenc/pkenc_gm82.py +98 -0
- charm/schemes/pkenc/pkenc_paillier99.py +118 -0
- charm/schemes/pkenc/pkenc_rabin.py +254 -0
- charm/schemes/pkenc/pkenc_rsa.py +186 -0
- charm/schemes/pksig/__init__.py +0 -0
- charm/schemes/pksig/pksig_CW13_z.py +135 -0
- charm/schemes/pksig/pksig_bls04.py +87 -0
- charm/schemes/pksig/pksig_boyen.py +156 -0
- charm/schemes/pksig/pksig_chch.py +97 -0
- charm/schemes/pksig/pksig_chp.py +70 -0
- charm/schemes/pksig/pksig_cl03.py +150 -0
- charm/schemes/pksig/pksig_cl04.py +87 -0
- charm/schemes/pksig/pksig_cllww12_z.py +142 -0
- charm/schemes/pksig/pksig_cyh.py +132 -0
- charm/schemes/pksig/pksig_dsa.py +76 -0
- charm/schemes/pksig/pksig_ecdsa.py +71 -0
- charm/schemes/pksig/pksig_hess.py +104 -0
- charm/schemes/pksig/pksig_hw.py +110 -0
- charm/schemes/pksig/pksig_lamport.py +63 -0
- charm/schemes/pksig/pksig_ps01.py +135 -0
- charm/schemes/pksig/pksig_ps02.py +124 -0
- charm/schemes/pksig/pksig_ps03.py +119 -0
- charm/schemes/pksig/pksig_rsa_hw09.py +206 -0
- charm/schemes/pksig/pksig_schnorr91.py +77 -0
- charm/schemes/pksig/pksig_waters.py +115 -0
- charm/schemes/pksig/pksig_waters05.py +121 -0
- charm/schemes/pksig/pksig_waters09.py +121 -0
- charm/schemes/pre_mg07.py +150 -0
- charm/schemes/prenc/pre_afgh06.py +126 -0
- charm/schemes/prenc/pre_bbs98.py +123 -0
- charm/schemes/prenc/pre_nal16.py +216 -0
- charm/schemes/protocol_a01.py +272 -0
- charm/schemes/protocol_ao00.py +215 -0
- charm/schemes/protocol_cns07.py +274 -0
- charm/schemes/protocol_schnorr91.py +125 -0
- charm/schemes/sigma1.py +64 -0
- charm/schemes/sigma2.py +129 -0
- charm/schemes/sigma3.py +126 -0
- charm/schemes/threshold/__init__.py +59 -0
- charm/schemes/threshold/dkls23_dkg.py +556 -0
- charm/schemes/threshold/dkls23_presign.py +1089 -0
- charm/schemes/threshold/dkls23_sign.py +761 -0
- charm/schemes/threshold/xrpl_wallet.py +967 -0
- charm/test/__init__.py +0 -0
- charm/test/adapters/__init__.py +0 -0
- charm/test/adapters/abenc_adapt_hybrid_test.py +29 -0
- charm/test/adapters/dabenc_adapt_hybrid_test.py +56 -0
- charm/test/adapters/ibenc_adapt_hybrid_test.py +36 -0
- charm/test/adapters/ibenc_adapt_identityhash_test.py +32 -0
- charm/test/adapters/kpabenc_adapt_hybrid_test.py +30 -0
- charm/test/benchmark/abenc_yllc15_bench.py +92 -0
- charm/test/benchmark/benchmark_test.py +148 -0
- charm/test/benchmark_threshold.py +260 -0
- charm/test/conftest.py +38 -0
- charm/test/fuzz/__init__.py +1 -0
- charm/test/fuzz/conftest.py +5 -0
- charm/test/fuzz/fuzz_policy_parser.py +76 -0
- charm/test/fuzz/fuzz_serialization.py +83 -0
- charm/test/schemes/__init__.py +0 -0
- charm/test/schemes/abenc/__init__.py +0 -0
- charm/test/schemes/abenc/abenc_bsw07_test.py +39 -0
- charm/test/schemes/abenc/abenc_dacmacs_yj14_test.py +16 -0
- charm/test/schemes/abenc/abenc_lsw08_test.py +33 -0
- charm/test/schemes/abenc/abenc_maabe_yj14_test.py +16 -0
- charm/test/schemes/abenc/abenc_tbpre_lww14_test.py +16 -0
- charm/test/schemes/abenc/abenc_waters09_test.py +38 -0
- charm/test/schemes/abenc/abenc_yllc15_test.py +74 -0
- charm/test/schemes/chamhash_adm05_test.py +31 -0
- charm/test/schemes/chamhash_rsa_hw09_test.py +29 -0
- charm/test/schemes/commit/__init__.py +0 -0
- charm/test/schemes/commit/commit_gs08_test.py +24 -0
- charm/test/schemes/commit/commit_pedersen92_test.py +26 -0
- charm/test/schemes/dabe_aw11_test.py +45 -0
- charm/test/schemes/encap_bchk05_test.py +21 -0
- charm/test/schemes/grpsig/__init__.py +0 -0
- charm/test/schemes/grpsig/groupsig_bgls04_test.py +35 -0
- charm/test/schemes/grpsig/groupsig_bgls04_var_test.py +39 -0
- charm/test/schemes/hibenc/__init__.py +0 -0
- charm/test/schemes/hibenc/hibenc_bb04_test.py +28 -0
- charm/test/schemes/ibenc/__init__.py +0 -0
- charm/test/schemes/ibenc/ibenc_bb03_test.py +26 -0
- charm/test/schemes/ibenc/ibenc_bf01_test.py +24 -0
- charm/test/schemes/ibenc/ibenc_ckrs09_test.py +25 -0
- charm/test/schemes/ibenc/ibenc_lsw08_test.py +31 -0
- charm/test/schemes/ibenc/ibenc_sw05_test.py +32 -0
- charm/test/schemes/ibenc/ibenc_waters05_test.py +31 -0
- charm/test/schemes/ibenc/ibenc_waters09_test.py +27 -0
- charm/test/schemes/pk_vrf_test.py +29 -0
- charm/test/schemes/pkenc/__init__.py +0 -0
- charm/test/schemes/pkenc_test.py +255 -0
- charm/test/schemes/pksig/__init__.py +0 -0
- charm/test/schemes/pksig_test.py +376 -0
- charm/test/schemes/rsa_alg_test.py +340 -0
- charm/test/schemes/threshold_test.py +1792 -0
- charm/test/serialize/__init__.py +0 -0
- charm/test/serialize/serialize_test.py +40 -0
- charm/test/toolbox/__init__.py +0 -0
- charm/test/toolbox/conversion_test.py +30 -0
- charm/test/toolbox/ecgroup_test.py +53 -0
- charm/test/toolbox/integer_arithmetic_test.py +441 -0
- charm/test/toolbox/paddingschemes_test.py +238 -0
- charm/test/toolbox/policy_parser_stress_test.py +969 -0
- charm/test/toolbox/secretshare_test.py +28 -0
- charm/test/toolbox/symcrypto_test.py +108 -0
- charm/test/toolbox/test_policy_expression.py +16 -0
- charm/test/vectors/__init__.py +1 -0
- charm/test/vectors/test_bls_vectors.py +289 -0
- charm/test/vectors/test_pedersen_vectors.py +315 -0
- charm/test/vectors/test_schnorr_vectors.py +368 -0
- charm/test/zkp_compiler/__init__.py +9 -0
- charm/test/zkp_compiler/benchmark_zkp.py +258 -0
- charm/test/zkp_compiler/test_and_proof.py +240 -0
- charm/test/zkp_compiler/test_batch_verify.py +248 -0
- charm/test/zkp_compiler/test_dleq_proof.py +264 -0
- charm/test/zkp_compiler/test_or_proof.py +231 -0
- charm/test/zkp_compiler/test_proof_serialization.py +121 -0
- charm/test/zkp_compiler/test_range_proof.py +241 -0
- charm/test/zkp_compiler/test_representation_proof.py +325 -0
- charm/test/zkp_compiler/test_schnorr_proof.py +221 -0
- charm/test/zkp_compiler/test_thread_safety.py +169 -0
- charm/test/zkp_compiler/test_zkp_parser.py +139 -0
- charm/toolbox/ABEnc.py +26 -0
- charm/toolbox/ABEncMultiAuth.py +66 -0
- charm/toolbox/ABEnumeric.py +800 -0
- charm/toolbox/Commit.py +24 -0
- charm/toolbox/DFA.py +89 -0
- charm/toolbox/FSA.py +1254 -0
- charm/toolbox/Hash.py +39 -0
- charm/toolbox/IBEnc.py +62 -0
- charm/toolbox/IBSig.py +64 -0
- charm/toolbox/PKEnc.py +66 -0
- charm/toolbox/PKSig.py +56 -0
- charm/toolbox/PREnc.py +32 -0
- charm/toolbox/ZKProof.py +289 -0
- charm/toolbox/__init__.py +0 -0
- charm/toolbox/bitstring.py +49 -0
- charm/toolbox/broadcast.py +220 -0
- charm/toolbox/conversion.py +100 -0
- charm/toolbox/eccurve.py +149 -0
- charm/toolbox/ecgroup.py +143 -0
- charm/toolbox/enum.py +60 -0
- charm/toolbox/hash_module.py +91 -0
- charm/toolbox/integergroup.py +323 -0
- charm/toolbox/iterate.py +22 -0
- charm/toolbox/matrixops.py +76 -0
- charm/toolbox/mpc_utils.py +296 -0
- charm/toolbox/msp.py +175 -0
- charm/toolbox/mta.py +985 -0
- charm/toolbox/node.py +120 -0
- charm/toolbox/ot/__init__.py +22 -0
- charm/toolbox/ot/base_ot.py +374 -0
- charm/toolbox/ot/dpf.py +642 -0
- charm/toolbox/ot/mpfss.py +228 -0
- charm/toolbox/ot/ot_extension.py +589 -0
- charm/toolbox/ot/silent_ot.py +378 -0
- charm/toolbox/paddingschemes.py +423 -0
- charm/toolbox/paddingschemes_test.py +238 -0
- charm/toolbox/pairingcurves.py +85 -0
- charm/toolbox/pairinggroup.py +186 -0
- charm/toolbox/policy_expression_spec.py +70 -0
- charm/toolbox/policytree.py +189 -0
- charm/toolbox/reCompiler.py +346 -0
- charm/toolbox/redundancyschemes.py +65 -0
- charm/toolbox/schemebase.py +188 -0
- charm/toolbox/secretshare.py +104 -0
- charm/toolbox/secretutil.py +174 -0
- charm/toolbox/securerandom.py +73 -0
- charm/toolbox/sigmaprotocol.py +46 -0
- charm/toolbox/specialprimes.py +45 -0
- charm/toolbox/symcrypto.py +279 -0
- charm/toolbox/threshold_sharing.py +553 -0
- charm/toolbox/xmlserialize.py +94 -0
- charm/toolbox/zknode.py +105 -0
- charm/zkp_compiler/__init__.py +89 -0
- charm/zkp_compiler/and_proof.py +460 -0
- charm/zkp_compiler/batch_verify.py +324 -0
- charm/zkp_compiler/dleq_proof.py +423 -0
- charm/zkp_compiler/or_proof.py +305 -0
- charm/zkp_compiler/range_proof.py +417 -0
- charm/zkp_compiler/representation_proof.py +466 -0
- charm/zkp_compiler/schnorr_proof.py +273 -0
- charm/zkp_compiler/thread_safe.py +150 -0
- charm/zkp_compiler/zk_demo.py +489 -0
- charm/zkp_compiler/zkp_factory.py +330 -0
- charm/zkp_compiler/zkp_generator.py +370 -0
- charm/zkp_compiler/zkparser.py +269 -0
- charm_crypto_framework-0.61.1.dist-info/METADATA +337 -0
- charm_crypto_framework-0.61.1.dist-info/RECORD +323 -0
- charm_crypto_framework-0.61.1.dist-info/WHEEL +5 -0
- charm_crypto_framework-0.61.1.dist-info/licenses/LICENSE.txt +165 -0
- charm_crypto_framework-0.61.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Batch Verification for Zero-Knowledge Proofs.
|
|
3
|
+
|
|
4
|
+
This module provides efficient batch verification of multiple ZKP proofs,
|
|
5
|
+
allowing verification of many proofs faster than verifying each individually.
|
|
6
|
+
|
|
7
|
+
=============================================================================
|
|
8
|
+
WHAT BATCH VERIFICATION DOES
|
|
9
|
+
=============================================================================
|
|
10
|
+
Batch verification allows verifying multiple proofs in a single operation
|
|
11
|
+
that is more efficient than verifying each proof individually. Instead of
|
|
12
|
+
performing n separate verifications, batch verification combines all proofs
|
|
13
|
+
into a single verification equation.
|
|
14
|
+
|
|
15
|
+
=============================================================================
|
|
16
|
+
HOW IT WORKS (Random Linear Combination Technique)
|
|
17
|
+
=============================================================================
|
|
18
|
+
For Schnorr proofs, each proof i has (ui, ci, zi) where:
|
|
19
|
+
- g^zi = ui * hi^ci (for valid proofs)
|
|
20
|
+
|
|
21
|
+
Batch verification:
|
|
22
|
+
1. For each proof i, pick random weight ρi ∈ Zq
|
|
23
|
+
2. Compute combined equation:
|
|
24
|
+
- LHS = g^(Σ ρi*zi)
|
|
25
|
+
- RHS = (Π ui^ρi) * (Π hi^(ρi*ci))
|
|
26
|
+
3. Check LHS == RHS
|
|
27
|
+
|
|
28
|
+
If all proofs are valid:
|
|
29
|
+
- g^zi = ui * hi^ci for each i
|
|
30
|
+
- Raising to ρi and multiplying: g^(Σ ρi*zi) = (Π ui^ρi) * (Π hi^(ρi*ci))
|
|
31
|
+
|
|
32
|
+
=============================================================================
|
|
33
|
+
SECURITY PROPERTIES
|
|
34
|
+
=============================================================================
|
|
35
|
+
- Soundness: If any proof is invalid, the batch check fails with
|
|
36
|
+
overwhelming probability (1 - 1/q where q is the group order).
|
|
37
|
+
- The random weights prevent a malicious prover from crafting proofs
|
|
38
|
+
that cancel out each other's errors.
|
|
39
|
+
|
|
40
|
+
=============================================================================
|
|
41
|
+
PERFORMANCE BENEFITS
|
|
42
|
+
=============================================================================
|
|
43
|
+
- Reduces the number of exponentiations from O(n) to O(1) for the base g
|
|
44
|
+
- Uses multi-exponentiation techniques for efficient product computation
|
|
45
|
+
- Typically 2-3x faster than individual verification for large batches
|
|
46
|
+
|
|
47
|
+
=============================================================================
|
|
48
|
+
USE CASES
|
|
49
|
+
=============================================================================
|
|
50
|
+
1. Blockchain verification - Verify many transaction proofs in a block
|
|
51
|
+
2. Credential systems - Batch verify multiple credential presentations
|
|
52
|
+
3. Voting systems - Efficiently verify all ballots in an election
|
|
53
|
+
4. Threshold signatures - Batch verify signature shares
|
|
54
|
+
|
|
55
|
+
Example usage::
|
|
56
|
+
|
|
57
|
+
from charm.toolbox.pairinggroup import PairingGroup, ZR, G1
|
|
58
|
+
from charm.zkp_compiler.batch_verify import BatchVerifier, batch_verify_schnorr
|
|
59
|
+
|
|
60
|
+
group = PairingGroup('SS512')
|
|
61
|
+
g = group.random(G1)
|
|
62
|
+
|
|
63
|
+
# Batch verify multiple Schnorr proofs
|
|
64
|
+
proofs_data = [
|
|
65
|
+
{'g': g, 'h': h1, 'proof': proof1},
|
|
66
|
+
{'g': g, 'h': h2, 'proof': proof2},
|
|
67
|
+
{'g': g, 'h': h3, 'proof': proof3},
|
|
68
|
+
]
|
|
69
|
+
all_valid = batch_verify_schnorr(group, proofs_data)
|
|
70
|
+
|
|
71
|
+
# Or use the BatchVerifier class
|
|
72
|
+
verifier = BatchVerifier(group)
|
|
73
|
+
verifier.add_schnorr_proof(g, h1, proof1)
|
|
74
|
+
verifier.add_schnorr_proof(g, h2, proof2)
|
|
75
|
+
all_valid = verifier.verify_all()
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
from charm.toolbox.pairinggroup import PairingGroup, ZR, G1
|
|
79
|
+
from charm.zkp_compiler.schnorr_proof import SchnorrProof, Proof
|
|
80
|
+
from charm.zkp_compiler.dleq_proof import DLEQProof, DLEQProofData
|
|
81
|
+
import logging
|
|
82
|
+
|
|
83
|
+
logger = logging.getLogger(__name__)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class BatchVerifier:
|
|
87
|
+
"""
|
|
88
|
+
Batch verifier for ZKP proofs.
|
|
89
|
+
|
|
90
|
+
Accumulates multiple proofs and verifies them all at once using
|
|
91
|
+
the random linear combination technique for efficiency.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
def __init__(self, group):
|
|
95
|
+
"""
|
|
96
|
+
Initialize batch verifier.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
group: The pairing group object
|
|
100
|
+
"""
|
|
101
|
+
self.group = group
|
|
102
|
+
self._schnorr_proofs = [] # List of (g, h, proof) tuples
|
|
103
|
+
self._dleq_proofs = [] # List of (g1, h1, g2, h2, proof) tuples
|
|
104
|
+
|
|
105
|
+
def add_schnorr_proof(self, g, h, proof):
|
|
106
|
+
"""
|
|
107
|
+
Add a Schnorr proof to the batch.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
g: The generator element
|
|
111
|
+
h: The public value h = g^x
|
|
112
|
+
proof: Proof object containing commitment, challenge, response
|
|
113
|
+
"""
|
|
114
|
+
self._schnorr_proofs.append((g, h, proof))
|
|
115
|
+
logger.debug("Added Schnorr proof to batch (total: %d)", len(self._schnorr_proofs))
|
|
116
|
+
|
|
117
|
+
def add_dleq_proof(self, g1, h1, g2, h2, proof):
|
|
118
|
+
"""
|
|
119
|
+
Add a DLEQ proof to the batch.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
g1: The first generator element
|
|
123
|
+
h1: The first public value h1 = g1^x
|
|
124
|
+
g2: The second generator element
|
|
125
|
+
h2: The second public value h2 = g2^x
|
|
126
|
+
proof: DLEQProofData object containing commitments, challenge, response
|
|
127
|
+
"""
|
|
128
|
+
self._dleq_proofs.append((g1, h1, g2, h2, proof))
|
|
129
|
+
logger.debug("Added DLEQ proof to batch (total: %d)", len(self._dleq_proofs))
|
|
130
|
+
|
|
131
|
+
def verify_all(self):
|
|
132
|
+
"""
|
|
133
|
+
Verify all proofs in the batch.
|
|
134
|
+
|
|
135
|
+
Uses random linear combination technique for efficiency.
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
True if all proofs are valid, False otherwise
|
|
139
|
+
"""
|
|
140
|
+
# Verify Schnorr proofs
|
|
141
|
+
if self._schnorr_proofs:
|
|
142
|
+
proofs_data = [
|
|
143
|
+
{'g': g, 'h': h, 'proof': proof}
|
|
144
|
+
for g, h, proof in self._schnorr_proofs
|
|
145
|
+
]
|
|
146
|
+
if not batch_verify_schnorr(self.group, proofs_data):
|
|
147
|
+
logger.debug("Batch Schnorr verification failed")
|
|
148
|
+
return False
|
|
149
|
+
|
|
150
|
+
# Verify DLEQ proofs
|
|
151
|
+
if self._dleq_proofs:
|
|
152
|
+
proofs_data = [
|
|
153
|
+
{'g1': g1, 'h1': h1, 'g2': g2, 'h2': h2, 'proof': proof}
|
|
154
|
+
for g1, h1, g2, h2, proof in self._dleq_proofs
|
|
155
|
+
]
|
|
156
|
+
if not batch_verify_dleq(self.group, proofs_data):
|
|
157
|
+
logger.debug("Batch DLEQ verification failed")
|
|
158
|
+
return False
|
|
159
|
+
|
|
160
|
+
logger.debug("Batch verification succeeded")
|
|
161
|
+
return True
|
|
162
|
+
|
|
163
|
+
def clear(self):
|
|
164
|
+
"""Clear all proofs from the batch."""
|
|
165
|
+
self._schnorr_proofs = []
|
|
166
|
+
self._dleq_proofs = []
|
|
167
|
+
logger.debug("Batch cleared")
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def batch_verify_schnorr(group, proofs_data):
|
|
171
|
+
"""
|
|
172
|
+
Batch verify multiple Schnorr proofs.
|
|
173
|
+
|
|
174
|
+
Uses random linear combination technique:
|
|
175
|
+
1. For each proof i with (ui, ci, zi), pick random weight ρi
|
|
176
|
+
2. Check: g^(Σ ρi*zi) == (Π ui^ρi) * (Π hi^(ρi*ci))
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
group: The pairing group
|
|
180
|
+
proofs_data: List of dicts with {'g': g, 'h': h, 'proof': proof}
|
|
181
|
+
where proof has commitment, challenge, and response attributes
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
True if all proofs are valid, False otherwise
|
|
185
|
+
"""
|
|
186
|
+
if not proofs_data:
|
|
187
|
+
return True
|
|
188
|
+
|
|
189
|
+
# First, verify all Fiat-Shamir challenges are correctly computed
|
|
190
|
+
for data in proofs_data:
|
|
191
|
+
g, h, proof = data['g'], data['h'], data['proof']
|
|
192
|
+
expected_challenge = SchnorrProof._compute_challenge_hash(
|
|
193
|
+
group, g, h, proof.commitment)
|
|
194
|
+
if expected_challenge != proof.challenge:
|
|
195
|
+
logger.debug("Schnorr challenge mismatch in batch verification")
|
|
196
|
+
return False
|
|
197
|
+
|
|
198
|
+
# Generate random weights for each proof
|
|
199
|
+
weights = [group.random(ZR) for _ in proofs_data]
|
|
200
|
+
|
|
201
|
+
# Compute LHS = g^(Σ ρi*zi)
|
|
202
|
+
# All proofs should use the same generator g for this optimization
|
|
203
|
+
# If generators differ, we compute the full product
|
|
204
|
+
first_g = proofs_data[0]['g']
|
|
205
|
+
same_generator = all(data['g'] == first_g for data in proofs_data)
|
|
206
|
+
|
|
207
|
+
if same_generator:
|
|
208
|
+
# Optimized case: single exponentiation for g
|
|
209
|
+
z_sum = sum(
|
|
210
|
+
(weights[i] * proofs_data[i]['proof'].response for i in range(len(proofs_data))),
|
|
211
|
+
group.init(ZR, 0)
|
|
212
|
+
)
|
|
213
|
+
lhs = first_g ** z_sum
|
|
214
|
+
else:
|
|
215
|
+
# General case: multi-exponentiation
|
|
216
|
+
lhs = group.init(G1, 1) # Identity element
|
|
217
|
+
for i, data in enumerate(proofs_data):
|
|
218
|
+
exp = weights[i] * data['proof'].response
|
|
219
|
+
lhs = lhs * (data['g'] ** exp)
|
|
220
|
+
|
|
221
|
+
# Compute RHS = (Π ui^ρi) * (Π hi^(ρi*ci))
|
|
222
|
+
rhs = group.init(G1, 1) # Identity element
|
|
223
|
+
for i, data in enumerate(proofs_data):
|
|
224
|
+
proof = data['proof']
|
|
225
|
+
rho = weights[i]
|
|
226
|
+
# Add ui^ρi
|
|
227
|
+
rhs = rhs * (proof.commitment ** rho)
|
|
228
|
+
# Add hi^(ρi*ci)
|
|
229
|
+
rhs = rhs * (data['h'] ** (rho * proof.challenge))
|
|
230
|
+
|
|
231
|
+
result = lhs == rhs
|
|
232
|
+
logger.debug("Batch Schnorr verification result: %s (n=%d)", result, len(proofs_data))
|
|
233
|
+
return result
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def batch_verify_dleq(group, proofs_data):
|
|
237
|
+
"""
|
|
238
|
+
Batch verify multiple DLEQ proofs.
|
|
239
|
+
|
|
240
|
+
Uses random linear combination technique extended for DLEQ:
|
|
241
|
+
For each proof i with (u1i, u2i, ci, zi), pick random weight ρi
|
|
242
|
+
Check two equations:
|
|
243
|
+
- g1^(Σ ρi*zi) == (Π u1i^ρi) * (Π h1i^(ρi*ci))
|
|
244
|
+
- g2^(Σ ρi*zi) == (Π u2i^ρi) * (Π h2i^(ρi*ci))
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
group: The pairing group
|
|
248
|
+
proofs_data: List of dicts with:
|
|
249
|
+
{'g1': g1, 'h1': h1, 'g2': g2, 'h2': h2, 'proof': proof}
|
|
250
|
+
where proof has commitment1, commitment2, challenge, response
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
True if all proofs are valid, False otherwise
|
|
254
|
+
"""
|
|
255
|
+
if not proofs_data:
|
|
256
|
+
return True
|
|
257
|
+
|
|
258
|
+
# First, verify all Fiat-Shamir challenges are correctly computed
|
|
259
|
+
for data in proofs_data:
|
|
260
|
+
g1, h1, g2, h2 = data['g1'], data['h1'], data['g2'], data['h2']
|
|
261
|
+
proof = data['proof']
|
|
262
|
+
expected_challenge = DLEQProof._compute_challenge_hash(
|
|
263
|
+
group, g1, h1, g2, h2, proof.commitment1, proof.commitment2)
|
|
264
|
+
if expected_challenge != proof.challenge:
|
|
265
|
+
logger.debug("DLEQ challenge mismatch in batch verification")
|
|
266
|
+
return False
|
|
267
|
+
|
|
268
|
+
# Generate random weights for each proof
|
|
269
|
+
weights = [group.random(ZR) for _ in proofs_data]
|
|
270
|
+
|
|
271
|
+
# Compute weighted sum of responses
|
|
272
|
+
z_sum = sum(
|
|
273
|
+
(weights[i] * proofs_data[i]['proof'].response for i in range(len(proofs_data))),
|
|
274
|
+
group.init(ZR, 0)
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
# Check first equation: g1^(Σ ρi*zi) == (Π u1i^ρi) * (Π h1i^(ρi*ci))
|
|
278
|
+
first_g1 = proofs_data[0]['g1']
|
|
279
|
+
same_g1 = all(data['g1'] == first_g1 for data in proofs_data)
|
|
280
|
+
|
|
281
|
+
if same_g1:
|
|
282
|
+
lhs1 = first_g1 ** z_sum
|
|
283
|
+
else:
|
|
284
|
+
lhs1 = group.init(G1, 1)
|
|
285
|
+
for i, data in enumerate(proofs_data):
|
|
286
|
+
exp = weights[i] * data['proof'].response
|
|
287
|
+
lhs1 = lhs1 * (data['g1'] ** exp)
|
|
288
|
+
|
|
289
|
+
rhs1 = group.init(G1, 1)
|
|
290
|
+
for i, data in enumerate(proofs_data):
|
|
291
|
+
proof = data['proof']
|
|
292
|
+
rho = weights[i]
|
|
293
|
+
rhs1 = rhs1 * (proof.commitment1 ** rho)
|
|
294
|
+
rhs1 = rhs1 * (data['h1'] ** (rho * proof.challenge))
|
|
295
|
+
|
|
296
|
+
if lhs1 != rhs1:
|
|
297
|
+
logger.debug("Batch DLEQ verification failed on first equation")
|
|
298
|
+
return False
|
|
299
|
+
|
|
300
|
+
# Check second equation: g2^(Σ ρi*zi) == (Π u2i^ρi) * (Π h2i^(ρi*ci))
|
|
301
|
+
first_g2 = proofs_data[0]['g2']
|
|
302
|
+
same_g2 = all(data['g2'] == first_g2 for data in proofs_data)
|
|
303
|
+
|
|
304
|
+
if same_g2:
|
|
305
|
+
lhs2 = first_g2 ** z_sum
|
|
306
|
+
else:
|
|
307
|
+
lhs2 = group.init(G1, 1)
|
|
308
|
+
for i, data in enumerate(proofs_data):
|
|
309
|
+
exp = weights[i] * data['proof'].response
|
|
310
|
+
lhs2 = lhs2 * (data['g2'] ** exp)
|
|
311
|
+
|
|
312
|
+
rhs2 = group.init(G1, 1)
|
|
313
|
+
for i, data in enumerate(proofs_data):
|
|
314
|
+
proof = data['proof']
|
|
315
|
+
rho = weights[i]
|
|
316
|
+
rhs2 = rhs2 * (proof.commitment2 ** rho)
|
|
317
|
+
rhs2 = rhs2 * (data['h2'] ** (rho * proof.challenge))
|
|
318
|
+
|
|
319
|
+
if lhs2 != rhs2:
|
|
320
|
+
logger.debug("Batch DLEQ verification failed on second equation")
|
|
321
|
+
return False
|
|
322
|
+
|
|
323
|
+
logger.debug("Batch DLEQ verification result: True (n=%d)", len(proofs_data))
|
|
324
|
+
return True
|