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,423 @@
1
+ """
2
+ DLEQ (Discrete Log Equality) Zero-Knowledge Proof implementation.
3
+
4
+ Also known as the Chaum-Pedersen protocol, this module provides proof of
5
+ knowledge that two discrete logarithms are equal without revealing the
6
+ secret exponent.
7
+
8
+ =============================================================================
9
+ WHAT DLEQ PROVES
10
+ =============================================================================
11
+ DLEQ proves: "I know x such that h1 = g1^x AND h2 = g2^x"
12
+
13
+ This is a proof of equality of discrete logs: the prover demonstrates that
14
+ the same secret exponent x was used to compute both h1 (relative to base g1)
15
+ and h2 (relative to base g2), without revealing x itself.
16
+
17
+ =============================================================================
18
+ MATHEMATICAL BASIS
19
+ =============================================================================
20
+ The protocol works as follows:
21
+
22
+ Interactive Version:
23
+ 1. Prover picks random r ∈ Zq
24
+ 2. Prover computes commitments: u1 = g1^r, u2 = g2^r
25
+ 3. Verifier sends random challenge c ∈ Zq
26
+ 4. Prover computes response: z = r + c*x (mod q)
27
+ 5. Verifier accepts if: g1^z == u1 * h1^c AND g2^z == u2 * h2^c
28
+
29
+ Correctness:
30
+ - If prover is honest: g1^z = g1^(r + c*x) = g1^r * g1^(c*x) = u1 * (g1^x)^c = u1 * h1^c ✓
31
+ - Same reasoning applies for the second equation with g2 and h2
32
+
33
+ Soundness:
34
+ - A cheating prover who knows x1 ≠ x2 where h1 = g1^x1 and h2 = g2^x2 cannot
35
+ produce a valid response z that satisfies both verification equations
36
+ (except with negligible probability)
37
+
38
+ =============================================================================
39
+ SECURITY PROPERTIES
40
+ =============================================================================
41
+ 1. HVZK (Honest-Verifier Zero-Knowledge):
42
+ - A simulator can produce transcripts indistinguishable from real proofs
43
+ - Simulator: pick random z, c; compute u1 = g1^z * h1^(-c), u2 = g2^z * h2^(-c)
44
+ - This transcript (u1, u2, c, z) is identically distributed to real proofs
45
+
46
+ 2. NIZK (Non-Interactive ZK via Fiat-Shamir):
47
+ - Replace interactive challenge with hash: c = H(g1, h1, g2, h2, u1, u2)
48
+ - Secure in the Random Oracle Model
49
+ - Produces publicly verifiable proofs
50
+
51
+ 3. Special Soundness:
52
+ - Given two accepting transcripts with same commitments but different
53
+ challenges (c, z) and (c', z'), one can extract: x = (z - z') / (c - c')
54
+
55
+ =============================================================================
56
+ USE CASES
57
+ =============================================================================
58
+ 1. Verifiable Random Functions (VRFs):
59
+ - Prove VRF output is correctly computed without revealing secret key
60
+
61
+ 2. ElGamal Re-encryption Proofs:
62
+ - Prove ciphertext was correctly re-randomized
63
+
64
+ 3. Threshold Cryptography:
65
+ - Prove partial decryption shares are correctly computed
66
+
67
+ 4. Voting Systems:
68
+ - Prove vote encryption uses consistent randomness
69
+
70
+ 5. Credential Systems:
71
+ - Prove different presentations derive from same credential
72
+
73
+ 6. Diffie-Hellman Tuple Proofs:
74
+ - Prove (g1, h1, g2, h2) is a valid DH tuple
75
+ """
76
+
77
+ from typing import Any
78
+
79
+ from charm.toolbox.pairinggroup import PairingGroup, ZR, G1
80
+ from charm.core.engine.util import objectToBytes, bytesToObject
81
+ import logging
82
+
83
+ logger = logging.getLogger(__name__)
84
+
85
+
86
+ class DLEQProofData:
87
+ """Container for DLEQ proof data with two commitments."""
88
+
89
+ def __init__(self, commitment1: Any, commitment2: Any, challenge: Any, response: Any, proof_type: str = 'dleq') -> None:
90
+ """
91
+ Initialize a DLEQ proof.
92
+
93
+ Args:
94
+ commitment1: The prover's first commitment (u1 = g1^r)
95
+ commitment2: The prover's second commitment (u2 = g2^r)
96
+ challenge: The challenge value (c)
97
+ response: The response value (z = r + c*x)
98
+ proof_type: Type identifier for the proof
99
+ """
100
+ self.commitment1 = commitment1
101
+ self.commitment2 = commitment2
102
+ self.challenge = challenge
103
+ self.response = response
104
+ self.proof_type = proof_type
105
+
106
+
107
+ class DLEQProof:
108
+ """
109
+ DLEQ (Discrete Log Equality) Zero-Knowledge Proof.
110
+
111
+ Proves knowledge of x such that h1 = g1^x AND h2 = g2^x without revealing x.
112
+ Also known as the Chaum-Pedersen protocol.
113
+
114
+ Supports both interactive and non-interactive (Fiat-Shamir) modes.
115
+
116
+ Example (non-interactive):
117
+ >>> group = PairingGroup('SS512')
118
+ >>> g1 = group.random(G1)
119
+ >>> g2 = group.random(G1)
120
+ >>> x = group.random(ZR) # Secret exponent
121
+ >>> h1 = g1 ** x
122
+ >>> h2 = g2 ** x
123
+ >>>
124
+ >>> # Prove h1 = g1^x and h2 = g2^x for the same x
125
+ >>> proof = DLEQProof.prove_non_interactive(group, g1, h1, g2, h2, x)
126
+ >>> assert DLEQProof.verify_non_interactive(group, g1, h1, g2, h2, proof)
127
+
128
+ Example (interactive):
129
+ >>> prover = DLEQProof.Prover(x, group)
130
+ >>> verifier = DLEQProof.Verifier(group)
131
+ >>>
132
+ >>> # Step 1: Prover creates commitments
133
+ >>> u1, u2 = prover.create_commitment(g1, g2)
134
+ >>>
135
+ >>> # Step 2: Verifier creates challenge
136
+ >>> c = verifier.create_challenge()
137
+ >>>
138
+ >>> # Step 3: Prover creates response
139
+ >>> z = prover.create_response(c)
140
+ >>>
141
+ >>> # Step 4: Verifier checks proof
142
+ >>> assert verifier.verify(g1, h1, g2, h2, u1, u2, z)
143
+ """
144
+
145
+ class Prover:
146
+ """Prover for DLEQ protocol."""
147
+
148
+ def __init__(self, secret_x, group):
149
+ """
150
+ Initialize prover with secret x.
151
+
152
+ Args:
153
+ secret_x: The secret discrete log value (same for both bases)
154
+ group: The pairing group object
155
+ """
156
+ self._r = None # Random commitment value (private)
157
+ self.group = group
158
+ self._x = secret_x # Secret (private)
159
+
160
+ def create_commitment(self, g1, g2):
161
+ """
162
+ Create prover's commitments: u1 = g1^r, u2 = g2^r.
163
+
164
+ Uses the same random r for both commitments to prove
165
+ equality of discrete logs.
166
+
167
+ Args:
168
+ g1: The first generator element
169
+ g2: The second generator element
170
+
171
+ Returns:
172
+ Tuple (u1, u2) where u1 = g1^r and u2 = g2^r
173
+ """
174
+ self._r = self.group.random(ZR)
175
+ u1 = g1 ** self._r
176
+ u2 = g2 ** self._r
177
+ logger.debug("Prover created DLEQ commitments")
178
+ return u1, u2
179
+
180
+ def create_response(self, challenge):
181
+ """
182
+ Create response to verifier's challenge: z = r + c*x.
183
+
184
+ Args:
185
+ challenge: The challenge value c from verifier
186
+
187
+ Returns:
188
+ The response z = r + c*x
189
+ """
190
+ if self._r is None:
191
+ raise ValueError("Must call create_commitment before create_response")
192
+ z = self._r + challenge * self._x
193
+ logger.debug("Prover created DLEQ response")
194
+ return z
195
+
196
+ class Verifier:
197
+ """Verifier for DLEQ protocol."""
198
+
199
+ def __init__(self, group):
200
+ """
201
+ Initialize verifier.
202
+
203
+ Args:
204
+ group: The pairing group object
205
+ """
206
+ self.group = group
207
+ self._c = None # Challenge (stored for verification)
208
+
209
+ def create_challenge(self):
210
+ """
211
+ Create random challenge c.
212
+
213
+ Returns:
214
+ Random challenge c in ZR
215
+ """
216
+ self._c = self.group.random(ZR)
217
+ logger.debug("Verifier created DLEQ challenge")
218
+ return self._c
219
+
220
+ def verify(self, g1, h1, g2, h2, commitment1, commitment2, response):
221
+ """
222
+ Verify DLEQ proof: g1^z == u1 * h1^c AND g2^z == u2 * h2^c.
223
+
224
+ Args:
225
+ g1: The first generator element
226
+ h1: The first public value h1 = g1^x
227
+ g2: The second generator element
228
+ h2: The second public value h2 = g2^x
229
+ commitment1: The prover's first commitment u1
230
+ commitment2: The prover's second commitment u2
231
+ response: The prover's response z
232
+
233
+ Returns:
234
+ True if proof is valid, False otherwise
235
+ """
236
+ if self._c is None:
237
+ raise ValueError("Must call create_challenge before verify")
238
+
239
+ # Check first equation: g1^z == u1 * h1^c
240
+ lhs1 = g1 ** response
241
+ rhs1 = commitment1 * (h1 ** self._c)
242
+ check1 = lhs1 == rhs1
243
+
244
+ # Check second equation: g2^z == u2 * h2^c
245
+ lhs2 = g2 ** response
246
+ rhs2 = commitment2 * (h2 ** self._c)
247
+ check2 = lhs2 == rhs2
248
+
249
+ result = check1 and check2
250
+ logger.debug("DLEQ verification result: %s (check1=%s, check2=%s)",
251
+ result, check1, check2)
252
+ return result
253
+
254
+ @classmethod
255
+ def _compute_challenge_hash(cls, group, g1, h1, g2, h2, commitment1, commitment2):
256
+ """
257
+ Compute Fiat-Shamir challenge as hash of all public values.
258
+
259
+ Args:
260
+ group: The pairing group
261
+ g1: First generator
262
+ h1: First public value h1 = g1^x
263
+ g2: Second generator
264
+ h2: Second public value h2 = g2^x
265
+ commitment1: First commitment u1 = g1^r
266
+ commitment2: Second commitment u2 = g2^r
267
+
268
+ Returns:
269
+ Challenge c as element of ZR
270
+ """
271
+ # Serialize all elements and concatenate for hashing
272
+ # Order: g1, h1, g2, h2, u1, u2 (matching protocol description)
273
+ data = (objectToBytes(g1, group) +
274
+ objectToBytes(h1, group) +
275
+ objectToBytes(g2, group) +
276
+ objectToBytes(h2, group) +
277
+ objectToBytes(commitment1, group) +
278
+ objectToBytes(commitment2, group))
279
+ return group.hash(data, ZR)
280
+
281
+ @classmethod
282
+ def prove_non_interactive(cls, group: PairingGroup, g1: Any, h1: Any, g2: Any, h2: Any, x: Any) -> DLEQProofData:
283
+ """
284
+ Generate non-interactive DLEQ proof using Fiat-Shamir heuristic.
285
+
286
+ Proves knowledge of x such that h1 = g1^x AND h2 = g2^x.
287
+
288
+ Args:
289
+ group: The pairing group
290
+ g1: The first generator element
291
+ h1: The first public value h1 = g1^x
292
+ g2: The second generator element
293
+ h2: The second public value h2 = g2^x
294
+ x: The secret discrete log (same for both equations)
295
+
296
+ Returns:
297
+ DLEQProofData object containing commitments, challenge, and response
298
+ """
299
+ # 1. Generate random r
300
+ r = group.random(ZR)
301
+
302
+ # 2. Compute commitments u1 = g1^r, u2 = g2^r
303
+ commitment1 = g1 ** r
304
+ commitment2 = g2 ** r
305
+
306
+ # 3. Compute challenge c = hash(g1, h1, g2, h2, u1, u2)
307
+ challenge = cls._compute_challenge_hash(
308
+ group, g1, h1, g2, h2, commitment1, commitment2)
309
+
310
+ # 4. Compute response z = r + c*x
311
+ response = r + challenge * x
312
+
313
+ logger.debug("Generated non-interactive DLEQ proof")
314
+ return DLEQProofData(
315
+ commitment1=commitment1,
316
+ commitment2=commitment2,
317
+ challenge=challenge,
318
+ response=response,
319
+ proof_type='dleq'
320
+ )
321
+
322
+ @classmethod
323
+ def verify_non_interactive(cls, group: PairingGroup, g1: Any, h1: Any, g2: Any, h2: Any, proof: DLEQProofData) -> bool:
324
+ """
325
+ Verify non-interactive DLEQ proof.
326
+
327
+ Args:
328
+ group: The pairing group
329
+ g1: The first generator element
330
+ h1: The first public value h1 = g1^x
331
+ g2: The second generator element
332
+ h2: The second public value h2 = g2^x
333
+ proof: DLEQProofData object containing commitments, challenge, and response
334
+
335
+ Returns:
336
+ True if proof is valid, False otherwise
337
+
338
+ Security Notes:
339
+ - Validates proof structure before verification
340
+ - Checks for identity element attacks
341
+ - Recomputes Fiat-Shamir challenge for consistency
342
+ """
343
+ # Security: Validate proof structure
344
+ required_attrs = ['commitment1', 'commitment2', 'challenge', 'response']
345
+ for attr in required_attrs:
346
+ if not hasattr(proof, attr):
347
+ logger.warning("Invalid DLEQ proof structure: missing '%s'. Ensure proof was created with DLEQProof.prove_non_interactive()", attr)
348
+ return False
349
+
350
+ # Security: Check for identity element (potential attack vector)
351
+ try:
352
+ identity = group.init(G1, 1)
353
+ if proof.commitment1 == identity or proof.commitment2 == identity:
354
+ logger.warning("Security: DLEQ proof commitment is identity element (possible attack). Proof rejected.")
355
+ return False
356
+ except Exception:
357
+ pass # Some groups may not support identity check
358
+
359
+ # Recompute challenge c = hash(g1, h1, g2, h2, u1, u2)
360
+ expected_challenge = cls._compute_challenge_hash(
361
+ group, g1, h1, g2, h2, proof.commitment1, proof.commitment2)
362
+
363
+ # Verify challenge matches (Fiat-Shamir consistency check)
364
+ if expected_challenge != proof.challenge:
365
+ logger.debug("Challenge mismatch in non-interactive DLEQ verification")
366
+ return False
367
+
368
+ # Check first equation: g1^z == u1 * h1^c
369
+ lhs1 = g1 ** proof.response
370
+ rhs1 = proof.commitment1 * (h1 ** proof.challenge)
371
+ check1 = lhs1 == rhs1
372
+
373
+ # Check second equation: g2^z == u2 * h2^c
374
+ lhs2 = g2 ** proof.response
375
+ rhs2 = proof.commitment2 * (h2 ** proof.challenge)
376
+ check2 = lhs2 == rhs2
377
+
378
+ result = check1 and check2
379
+ logger.debug("Non-interactive DLEQ verification result: %s (check1=%s, check2=%s)",
380
+ result, check1, check2)
381
+ return result
382
+
383
+ @classmethod
384
+ def serialize_proof(cls, proof: DLEQProofData, group: PairingGroup) -> bytes:
385
+ """
386
+ Serialize DLEQ proof to bytes using Charm utilities.
387
+
388
+ Args:
389
+ proof: DLEQProofData object to serialize
390
+ group: The pairing group
391
+
392
+ Returns:
393
+ Bytes representation of the proof
394
+ """
395
+ proof_dict = {
396
+ 'commitment1': proof.commitment1,
397
+ 'commitment2': proof.commitment2,
398
+ 'challenge': proof.challenge,
399
+ 'response': proof.response,
400
+ 'proof_type': proof.proof_type
401
+ }
402
+ return objectToBytes(proof_dict, group)
403
+
404
+ @classmethod
405
+ def deserialize_proof(cls, data: bytes, group: PairingGroup) -> DLEQProofData:
406
+ """
407
+ Deserialize bytes to DLEQ proof.
408
+
409
+ Args:
410
+ data: Bytes to deserialize
411
+ group: The pairing group
412
+
413
+ Returns:
414
+ DLEQProofData object
415
+ """
416
+ proof_dict = bytesToObject(data, group)
417
+ return DLEQProofData(
418
+ commitment1=proof_dict['commitment1'],
419
+ commitment2=proof_dict['commitment2'],
420
+ challenge=proof_dict['challenge'],
421
+ response=proof_dict['response'],
422
+ proof_type=proof_dict.get('proof_type', 'dleq')
423
+ )