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.
Files changed (323) hide show
  1. charm/__init__.py +5 -0
  2. charm/adapters/__init__.py +0 -0
  3. charm/adapters/abenc_adapt_hybrid.py +90 -0
  4. charm/adapters/dabenc_adapt_hybrid.py +145 -0
  5. charm/adapters/ibenc_adapt_hybrid.py +72 -0
  6. charm/adapters/ibenc_adapt_identityhash.py +80 -0
  7. charm/adapters/kpabenc_adapt_hybrid.py +91 -0
  8. charm/adapters/pkenc_adapt_bchk05.py +121 -0
  9. charm/adapters/pkenc_adapt_chk04.py +91 -0
  10. charm/adapters/pkenc_adapt_hybrid.py +98 -0
  11. charm/adapters/pksig_adapt_naor01.py +89 -0
  12. charm/config.py +7 -0
  13. charm/core/__init__.py +0 -0
  14. charm/core/benchmark/benchmark_util.c +353 -0
  15. charm/core/benchmark/benchmark_util.h +61 -0
  16. charm/core/benchmark/benchmarkmodule.c +476 -0
  17. charm/core/benchmark/benchmarkmodule.h +162 -0
  18. charm/core/benchmark.cpython-313-darwin.so +0 -0
  19. charm/core/crypto/AES/AES.c +1464 -0
  20. charm/core/crypto/AES.cpython-313-darwin.so +0 -0
  21. charm/core/crypto/DES/DES.c +113 -0
  22. charm/core/crypto/DES.cpython-313-darwin.so +0 -0
  23. charm/core/crypto/DES3/DES3.c +26 -0
  24. charm/core/crypto/DES3.cpython-313-darwin.so +0 -0
  25. charm/core/crypto/__init__.py +0 -0
  26. charm/core/crypto/cryptobase/XOR.c +80 -0
  27. charm/core/crypto/cryptobase/_counter.c +496 -0
  28. charm/core/crypto/cryptobase/_counter.h +54 -0
  29. charm/core/crypto/cryptobase/block_template.c +900 -0
  30. charm/core/crypto/cryptobase/block_template.h +69 -0
  31. charm/core/crypto/cryptobase/cryptobasemodule.c +220 -0
  32. charm/core/crypto/cryptobase/libtom/tomcrypt.h +90 -0
  33. charm/core/crypto/cryptobase/libtom/tomcrypt_argchk.h +44 -0
  34. charm/core/crypto/cryptobase/libtom/tomcrypt_cfg.h +186 -0
  35. charm/core/crypto/cryptobase/libtom/tomcrypt_cipher.h +941 -0
  36. charm/core/crypto/cryptobase/libtom/tomcrypt_custom.h +556 -0
  37. charm/core/crypto/cryptobase/libtom/tomcrypt_des.c +1912 -0
  38. charm/core/crypto/cryptobase/libtom/tomcrypt_hash.h +407 -0
  39. charm/core/crypto/cryptobase/libtom/tomcrypt_mac.h +496 -0
  40. charm/core/crypto/cryptobase/libtom/tomcrypt_macros.h +435 -0
  41. charm/core/crypto/cryptobase/libtom/tomcrypt_math.h +534 -0
  42. charm/core/crypto/cryptobase/libtom/tomcrypt_misc.h +103 -0
  43. charm/core/crypto/cryptobase/libtom/tomcrypt_pk.h +653 -0
  44. charm/core/crypto/cryptobase/libtom/tomcrypt_pkcs.h +90 -0
  45. charm/core/crypto/cryptobase/libtom/tomcrypt_prng.h +199 -0
  46. charm/core/crypto/cryptobase/stream_template.c +271 -0
  47. charm/core/crypto/cryptobase/strxor.c +229 -0
  48. charm/core/crypto/cryptobase.cpython-313-darwin.so +0 -0
  49. charm/core/engine/__init__.py +5 -0
  50. charm/core/engine/protocol.py +293 -0
  51. charm/core/engine/util.py +174 -0
  52. charm/core/math/__init__.py +0 -0
  53. charm/core/math/elliptic_curve/ecmodule.c +1986 -0
  54. charm/core/math/elliptic_curve/ecmodule.h +230 -0
  55. charm/core/math/elliptic_curve.cpython-313-darwin.so +0 -0
  56. charm/core/math/elliptic_curve.pyi +63 -0
  57. charm/core/math/integer/integermodule.c +2539 -0
  58. charm/core/math/integer/integermodule.h +145 -0
  59. charm/core/math/integer.cpython-313-darwin.so +0 -0
  60. charm/core/math/integer.pyi +76 -0
  61. charm/core/math/pairing/miracl/miracl_config.h +37 -0
  62. charm/core/math/pairing/miracl/miracl_interface.h +118 -0
  63. charm/core/math/pairing/miracl/miracl_interface2.h +126 -0
  64. charm/core/math/pairing/miracl/pairingmodule2.c +2094 -0
  65. charm/core/math/pairing/miracl/pairingmodule2.h +307 -0
  66. charm/core/math/pairing/pairingmodule.c +2230 -0
  67. charm/core/math/pairing/pairingmodule.h +241 -0
  68. charm/core/math/pairing/relic/pairingmodule3.c +1853 -0
  69. charm/core/math/pairing/relic/pairingmodule3.h +233 -0
  70. charm/core/math/pairing/relic/relic_interface.c +1337 -0
  71. charm/core/math/pairing/relic/relic_interface.h +217 -0
  72. charm/core/math/pairing/relic/test_relic.c +171 -0
  73. charm/core/math/pairing.cpython-313-darwin.so +0 -0
  74. charm/core/math/pairing.pyi +69 -0
  75. charm/core/utilities/base64.c +248 -0
  76. charm/core/utilities/base64.h +15 -0
  77. charm/schemes/__init__.py +0 -0
  78. charm/schemes/abenc/__init__.py +0 -0
  79. charm/schemes/abenc/abenc_accountability_jyjxgd20.py +647 -0
  80. charm/schemes/abenc/abenc_bsw07.py +146 -0
  81. charm/schemes/abenc/abenc_ca_cpabe_ar17.py +684 -0
  82. charm/schemes/abenc/abenc_dacmacs_yj14.py +298 -0
  83. charm/schemes/abenc/abenc_lsw08.py +159 -0
  84. charm/schemes/abenc/abenc_maabe_rw15.py +236 -0
  85. charm/schemes/abenc/abenc_maabe_yj14.py +297 -0
  86. charm/schemes/abenc/abenc_tbpre_lww14.py +309 -0
  87. charm/schemes/abenc/abenc_unmcpabe_yahk14.py +223 -0
  88. charm/schemes/abenc/abenc_waters09.py +144 -0
  89. charm/schemes/abenc/abenc_yct14.py +208 -0
  90. charm/schemes/abenc/abenc_yllc15.py +178 -0
  91. charm/schemes/abenc/ac17.py +248 -0
  92. charm/schemes/abenc/bsw07.py +141 -0
  93. charm/schemes/abenc/cgw15.py +277 -0
  94. charm/schemes/abenc/dabe_aw11.py +204 -0
  95. charm/schemes/abenc/dfa_fe12.py +144 -0
  96. charm/schemes/abenc/pk_hve08.py +179 -0
  97. charm/schemes/abenc/waters11.py +143 -0
  98. charm/schemes/aggrsign_MuSig.py +150 -0
  99. charm/schemes/aggrsign_bls.py +267 -0
  100. charm/schemes/blindsig_ps16.py +654 -0
  101. charm/schemes/chamhash_adm05.py +113 -0
  102. charm/schemes/chamhash_rsa_hw09.py +100 -0
  103. charm/schemes/commit/__init__.py +0 -0
  104. charm/schemes/commit/commit_gs08.py +77 -0
  105. charm/schemes/commit/commit_pedersen92.py +53 -0
  106. charm/schemes/encap_bchk05.py +62 -0
  107. charm/schemes/grpsig/__init__.py +0 -0
  108. charm/schemes/grpsig/groupsig_bgls04.py +114 -0
  109. charm/schemes/grpsig/groupsig_bgls04_var.py +115 -0
  110. charm/schemes/hibenc/__init__.py +0 -0
  111. charm/schemes/hibenc/hibenc_bb04.py +105 -0
  112. charm/schemes/hibenc/hibenc_lew11.py +193 -0
  113. charm/schemes/ibenc/__init__.py +0 -0
  114. charm/schemes/ibenc/clpkc_rp03.py +119 -0
  115. charm/schemes/ibenc/ibenc_CW13_z.py +168 -0
  116. charm/schemes/ibenc/ibenc_bb03.py +94 -0
  117. charm/schemes/ibenc/ibenc_bf01.py +121 -0
  118. charm/schemes/ibenc/ibenc_ckrs09.py +120 -0
  119. charm/schemes/ibenc/ibenc_cllww12_z.py +172 -0
  120. charm/schemes/ibenc/ibenc_lsw08.py +120 -0
  121. charm/schemes/ibenc/ibenc_sw05.py +238 -0
  122. charm/schemes/ibenc/ibenc_waters05.py +144 -0
  123. charm/schemes/ibenc/ibenc_waters05_z.py +164 -0
  124. charm/schemes/ibenc/ibenc_waters09.py +107 -0
  125. charm/schemes/ibenc/ibenc_waters09_z.py +147 -0
  126. charm/schemes/joye_scheme.py +106 -0
  127. charm/schemes/lem_scheme.py +207 -0
  128. charm/schemes/pk_fre_ccv11.py +107 -0
  129. charm/schemes/pk_vrf.py +127 -0
  130. charm/schemes/pkenc/__init__.py +0 -0
  131. charm/schemes/pkenc/pkenc_cs98.py +108 -0
  132. charm/schemes/pkenc/pkenc_elgamal85.py +122 -0
  133. charm/schemes/pkenc/pkenc_gm82.py +98 -0
  134. charm/schemes/pkenc/pkenc_paillier99.py +118 -0
  135. charm/schemes/pkenc/pkenc_rabin.py +254 -0
  136. charm/schemes/pkenc/pkenc_rsa.py +186 -0
  137. charm/schemes/pksig/__init__.py +0 -0
  138. charm/schemes/pksig/pksig_CW13_z.py +135 -0
  139. charm/schemes/pksig/pksig_bls04.py +87 -0
  140. charm/schemes/pksig/pksig_boyen.py +156 -0
  141. charm/schemes/pksig/pksig_chch.py +97 -0
  142. charm/schemes/pksig/pksig_chp.py +70 -0
  143. charm/schemes/pksig/pksig_cl03.py +150 -0
  144. charm/schemes/pksig/pksig_cl04.py +87 -0
  145. charm/schemes/pksig/pksig_cllww12_z.py +142 -0
  146. charm/schemes/pksig/pksig_cyh.py +132 -0
  147. charm/schemes/pksig/pksig_dsa.py +76 -0
  148. charm/schemes/pksig/pksig_ecdsa.py +71 -0
  149. charm/schemes/pksig/pksig_hess.py +104 -0
  150. charm/schemes/pksig/pksig_hw.py +110 -0
  151. charm/schemes/pksig/pksig_lamport.py +63 -0
  152. charm/schemes/pksig/pksig_ps01.py +135 -0
  153. charm/schemes/pksig/pksig_ps02.py +124 -0
  154. charm/schemes/pksig/pksig_ps03.py +119 -0
  155. charm/schemes/pksig/pksig_rsa_hw09.py +206 -0
  156. charm/schemes/pksig/pksig_schnorr91.py +77 -0
  157. charm/schemes/pksig/pksig_waters.py +115 -0
  158. charm/schemes/pksig/pksig_waters05.py +121 -0
  159. charm/schemes/pksig/pksig_waters09.py +121 -0
  160. charm/schemes/pre_mg07.py +150 -0
  161. charm/schemes/prenc/pre_afgh06.py +126 -0
  162. charm/schemes/prenc/pre_bbs98.py +123 -0
  163. charm/schemes/prenc/pre_nal16.py +216 -0
  164. charm/schemes/protocol_a01.py +272 -0
  165. charm/schemes/protocol_ao00.py +215 -0
  166. charm/schemes/protocol_cns07.py +274 -0
  167. charm/schemes/protocol_schnorr91.py +125 -0
  168. charm/schemes/sigma1.py +64 -0
  169. charm/schemes/sigma2.py +129 -0
  170. charm/schemes/sigma3.py +126 -0
  171. charm/schemes/threshold/__init__.py +59 -0
  172. charm/schemes/threshold/dkls23_dkg.py +556 -0
  173. charm/schemes/threshold/dkls23_presign.py +1089 -0
  174. charm/schemes/threshold/dkls23_sign.py +761 -0
  175. charm/schemes/threshold/xrpl_wallet.py +967 -0
  176. charm/test/__init__.py +0 -0
  177. charm/test/adapters/__init__.py +0 -0
  178. charm/test/adapters/abenc_adapt_hybrid_test.py +29 -0
  179. charm/test/adapters/dabenc_adapt_hybrid_test.py +56 -0
  180. charm/test/adapters/ibenc_adapt_hybrid_test.py +36 -0
  181. charm/test/adapters/ibenc_adapt_identityhash_test.py +32 -0
  182. charm/test/adapters/kpabenc_adapt_hybrid_test.py +30 -0
  183. charm/test/benchmark/abenc_yllc15_bench.py +92 -0
  184. charm/test/benchmark/benchmark_test.py +148 -0
  185. charm/test/benchmark_threshold.py +260 -0
  186. charm/test/conftest.py +38 -0
  187. charm/test/fuzz/__init__.py +1 -0
  188. charm/test/fuzz/conftest.py +5 -0
  189. charm/test/fuzz/fuzz_policy_parser.py +76 -0
  190. charm/test/fuzz/fuzz_serialization.py +83 -0
  191. charm/test/schemes/__init__.py +0 -0
  192. charm/test/schemes/abenc/__init__.py +0 -0
  193. charm/test/schemes/abenc/abenc_bsw07_test.py +39 -0
  194. charm/test/schemes/abenc/abenc_dacmacs_yj14_test.py +16 -0
  195. charm/test/schemes/abenc/abenc_lsw08_test.py +33 -0
  196. charm/test/schemes/abenc/abenc_maabe_yj14_test.py +16 -0
  197. charm/test/schemes/abenc/abenc_tbpre_lww14_test.py +16 -0
  198. charm/test/schemes/abenc/abenc_waters09_test.py +38 -0
  199. charm/test/schemes/abenc/abenc_yllc15_test.py +74 -0
  200. charm/test/schemes/chamhash_adm05_test.py +31 -0
  201. charm/test/schemes/chamhash_rsa_hw09_test.py +29 -0
  202. charm/test/schemes/commit/__init__.py +0 -0
  203. charm/test/schemes/commit/commit_gs08_test.py +24 -0
  204. charm/test/schemes/commit/commit_pedersen92_test.py +26 -0
  205. charm/test/schemes/dabe_aw11_test.py +45 -0
  206. charm/test/schemes/encap_bchk05_test.py +21 -0
  207. charm/test/schemes/grpsig/__init__.py +0 -0
  208. charm/test/schemes/grpsig/groupsig_bgls04_test.py +35 -0
  209. charm/test/schemes/grpsig/groupsig_bgls04_var_test.py +39 -0
  210. charm/test/schemes/hibenc/__init__.py +0 -0
  211. charm/test/schemes/hibenc/hibenc_bb04_test.py +28 -0
  212. charm/test/schemes/ibenc/__init__.py +0 -0
  213. charm/test/schemes/ibenc/ibenc_bb03_test.py +26 -0
  214. charm/test/schemes/ibenc/ibenc_bf01_test.py +24 -0
  215. charm/test/schemes/ibenc/ibenc_ckrs09_test.py +25 -0
  216. charm/test/schemes/ibenc/ibenc_lsw08_test.py +31 -0
  217. charm/test/schemes/ibenc/ibenc_sw05_test.py +32 -0
  218. charm/test/schemes/ibenc/ibenc_waters05_test.py +31 -0
  219. charm/test/schemes/ibenc/ibenc_waters09_test.py +27 -0
  220. charm/test/schemes/pk_vrf_test.py +29 -0
  221. charm/test/schemes/pkenc/__init__.py +0 -0
  222. charm/test/schemes/pkenc_test.py +255 -0
  223. charm/test/schemes/pksig/__init__.py +0 -0
  224. charm/test/schemes/pksig_test.py +376 -0
  225. charm/test/schemes/rsa_alg_test.py +340 -0
  226. charm/test/schemes/threshold_test.py +1792 -0
  227. charm/test/serialize/__init__.py +0 -0
  228. charm/test/serialize/serialize_test.py +40 -0
  229. charm/test/toolbox/__init__.py +0 -0
  230. charm/test/toolbox/conversion_test.py +30 -0
  231. charm/test/toolbox/ecgroup_test.py +53 -0
  232. charm/test/toolbox/integer_arithmetic_test.py +441 -0
  233. charm/test/toolbox/paddingschemes_test.py +238 -0
  234. charm/test/toolbox/policy_parser_stress_test.py +969 -0
  235. charm/test/toolbox/secretshare_test.py +28 -0
  236. charm/test/toolbox/symcrypto_test.py +108 -0
  237. charm/test/toolbox/test_policy_expression.py +16 -0
  238. charm/test/vectors/__init__.py +1 -0
  239. charm/test/vectors/test_bls_vectors.py +289 -0
  240. charm/test/vectors/test_pedersen_vectors.py +315 -0
  241. charm/test/vectors/test_schnorr_vectors.py +368 -0
  242. charm/test/zkp_compiler/__init__.py +9 -0
  243. charm/test/zkp_compiler/benchmark_zkp.py +258 -0
  244. charm/test/zkp_compiler/test_and_proof.py +240 -0
  245. charm/test/zkp_compiler/test_batch_verify.py +248 -0
  246. charm/test/zkp_compiler/test_dleq_proof.py +264 -0
  247. charm/test/zkp_compiler/test_or_proof.py +231 -0
  248. charm/test/zkp_compiler/test_proof_serialization.py +121 -0
  249. charm/test/zkp_compiler/test_range_proof.py +241 -0
  250. charm/test/zkp_compiler/test_representation_proof.py +325 -0
  251. charm/test/zkp_compiler/test_schnorr_proof.py +221 -0
  252. charm/test/zkp_compiler/test_thread_safety.py +169 -0
  253. charm/test/zkp_compiler/test_zkp_parser.py +139 -0
  254. charm/toolbox/ABEnc.py +26 -0
  255. charm/toolbox/ABEncMultiAuth.py +66 -0
  256. charm/toolbox/ABEnumeric.py +800 -0
  257. charm/toolbox/Commit.py +24 -0
  258. charm/toolbox/DFA.py +89 -0
  259. charm/toolbox/FSA.py +1254 -0
  260. charm/toolbox/Hash.py +39 -0
  261. charm/toolbox/IBEnc.py +62 -0
  262. charm/toolbox/IBSig.py +64 -0
  263. charm/toolbox/PKEnc.py +66 -0
  264. charm/toolbox/PKSig.py +56 -0
  265. charm/toolbox/PREnc.py +32 -0
  266. charm/toolbox/ZKProof.py +289 -0
  267. charm/toolbox/__init__.py +0 -0
  268. charm/toolbox/bitstring.py +49 -0
  269. charm/toolbox/broadcast.py +220 -0
  270. charm/toolbox/conversion.py +100 -0
  271. charm/toolbox/eccurve.py +149 -0
  272. charm/toolbox/ecgroup.py +143 -0
  273. charm/toolbox/enum.py +60 -0
  274. charm/toolbox/hash_module.py +91 -0
  275. charm/toolbox/integergroup.py +323 -0
  276. charm/toolbox/iterate.py +22 -0
  277. charm/toolbox/matrixops.py +76 -0
  278. charm/toolbox/mpc_utils.py +296 -0
  279. charm/toolbox/msp.py +175 -0
  280. charm/toolbox/mta.py +985 -0
  281. charm/toolbox/node.py +120 -0
  282. charm/toolbox/ot/__init__.py +22 -0
  283. charm/toolbox/ot/base_ot.py +374 -0
  284. charm/toolbox/ot/dpf.py +642 -0
  285. charm/toolbox/ot/mpfss.py +228 -0
  286. charm/toolbox/ot/ot_extension.py +589 -0
  287. charm/toolbox/ot/silent_ot.py +378 -0
  288. charm/toolbox/paddingschemes.py +423 -0
  289. charm/toolbox/paddingschemes_test.py +238 -0
  290. charm/toolbox/pairingcurves.py +85 -0
  291. charm/toolbox/pairinggroup.py +186 -0
  292. charm/toolbox/policy_expression_spec.py +70 -0
  293. charm/toolbox/policytree.py +189 -0
  294. charm/toolbox/reCompiler.py +346 -0
  295. charm/toolbox/redundancyschemes.py +65 -0
  296. charm/toolbox/schemebase.py +188 -0
  297. charm/toolbox/secretshare.py +104 -0
  298. charm/toolbox/secretutil.py +174 -0
  299. charm/toolbox/securerandom.py +73 -0
  300. charm/toolbox/sigmaprotocol.py +46 -0
  301. charm/toolbox/specialprimes.py +45 -0
  302. charm/toolbox/symcrypto.py +279 -0
  303. charm/toolbox/threshold_sharing.py +553 -0
  304. charm/toolbox/xmlserialize.py +94 -0
  305. charm/toolbox/zknode.py +105 -0
  306. charm/zkp_compiler/__init__.py +89 -0
  307. charm/zkp_compiler/and_proof.py +460 -0
  308. charm/zkp_compiler/batch_verify.py +324 -0
  309. charm/zkp_compiler/dleq_proof.py +423 -0
  310. charm/zkp_compiler/or_proof.py +305 -0
  311. charm/zkp_compiler/range_proof.py +417 -0
  312. charm/zkp_compiler/representation_proof.py +466 -0
  313. charm/zkp_compiler/schnorr_proof.py +273 -0
  314. charm/zkp_compiler/thread_safe.py +150 -0
  315. charm/zkp_compiler/zk_demo.py +489 -0
  316. charm/zkp_compiler/zkp_factory.py +330 -0
  317. charm/zkp_compiler/zkp_generator.py +370 -0
  318. charm/zkp_compiler/zkparser.py +269 -0
  319. charm_crypto_framework-0.61.1.dist-info/METADATA +337 -0
  320. charm_crypto_framework-0.61.1.dist-info/RECORD +323 -0
  321. charm_crypto_framework-0.61.1.dist-info/WHEEL +5 -0
  322. charm_crypto_framework-0.61.1.dist-info/licenses/LICENSE.txt +165 -0
  323. 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